#!/usr/bin/env python3
# -*- Mode: Python -*-
# ai_lecture-01.py
# Author : Marcel Turcotte & ChatGPT 5
# Created On : Tue Feb 13 16:29:41 2024
# Last Modified By: Marcel Turcotte
# Last Modified On: Thu Aug 28 15:03:14 EDT 2025
# In 2024, I developed the initial version of this script.
# This year, I used ChatGPT to revise the code to align with the most recent API version,
# enhance its educational value by incorporating detailed comments,
# and improve its suitability as an instructive example.
"""
Didactic example: translate EN->Canadian French, then synthesize audio in EN & FR.
CLI options:
--format : audio output format (mp3, wav, etc.)
--voice : TTS voice (e.g., nova, alloy, verse, etc.)
--model : TTS model (tts-1-hd for high quality, gpt-4o-mini-tts for low latency)
Examples:
python ai_lecture-01.py --format mp3 --voice nova --model tts-1-hd
python ai_lecture-01.py --format wav --voice alloy --model gpt-4o-mini-tts
"""
from __future__ import annotations
import os
import argparse
from pathlib import Path
from openai import OpenAI, APIError, APIConnectionError, APITimeoutError
# -------------------------------------------------------
# Configuration
# -------------------------------------------------------
client = OpenAI() # Reads OPENAI_API_KEY from environment
# -------------------------------------------------------
# Text Utilities
# -------------------------------------------------------
def translate_to_canadian_french(input_text: str) -> str:
"""Translate English text to Canadian French (CSI4106→CSI4506)."""
instructions = (
"You are a careful translator. Translate the user's English text into Canadian French. "
"Preserve technical terms and course names. "
'If the course code "CSI4106" appears, translate it as "CSI4506".'
)
try:
resp = client.responses.create(
model="gpt-4o",
instructions=instructions,
input=input_text,
temperature=0.2,
max_output_tokens=1200,
)
return resp.output_text or ""
except (APIConnectionError, APITimeoutError) as net_err:
print(f"[Network issue] {net_err}")
except APIError as api_err:
print(f"[OpenAI API error] {api_err}")
except Exception as e:
print(f"[Unexpected error] {e}")
return ""
# -------------------------------------------------------
# Audio Utilities
# -------------------------------------------------------
def synthesize_speech(
text: str,
output_path: Path,
*,
model: str = "tts-1-hd",
voice: str = "nova",
response_format: str = "mp3",
) -> bool:
"""
Stream synthesized speech to a file on disk.
Returns True on success, False otherwise.
"""
output_path.parent.mkdir(parents=True, exist_ok=True)
try:
with client.audio.speech.with_streaming_response.create(
model=model,
voice=voice,
input=text,
response_format=response_format,
) as response:
response.stream_to_file(str(output_path))
return True
except (APIConnectionError, APITimeoutError) as net_err:
print(f"[Network issue] {net_err}")
except APIError as api_err:
print(f"[OpenAI API error] {api_err}")
except Exception as e:
print(f"[Unexpected error] {e}")
return False
# -------------------------------------------------------
# Example script logic
# -------------------------------------------------------
def main(audio_format: str, voice: str, model: str) -> None:
"""Translate the course intro and synthesize EN & FR audio files."""
input_text_en = (
'Welcome to CSI4106, "introduction to artificial intelligence"! '
"In this course, you will learn about the roots and scope of Artificial Intelligence. "
"Knowledge and knowledge representation. Search, informed search, adversarial search. "
"Deduction and reasoning. Uncertainty in Artificial Intelligence. "
"Introduction to Natural Language Processing. Elements of planning. Basics of Machine Learning."
)
input_text_fr = translate_to_canadian_french(input_text_en)
if not input_text_fr:
print("[Warning] Translation failed; defaulting to English text only.")
speech_file_path_fr = Path(f"01_tts_course_description-fr-{voice}.{audio_format}")
speech_file_path_en = Path(f"01_tts_course_description-en-{voice}.{audio_format}")
if input_text_fr:
ok_fr = synthesize_speech(
input_text_fr, speech_file_path_fr, model=model, voice=voice, response_format=audio_format
)
print(f"[{'OK' if ok_fr else 'Error'}] FR audio → {speech_file_path_fr}")
ok_en = synthesize_speech(
input_text_en, speech_file_path_en, model=model, voice=voice, response_format=audio_format
)
print(f"[{'OK' if ok_en else 'Error'}] EN audio → {speech_file_path_en}")
if __name__ == "__main__":
if not os.getenv("OPENAI_API_KEY"):
raise RuntimeError("OPENAI_API_KEY is not set in environment or .env file.")
parser = argparse.ArgumentParser(description="Translate course intro and synthesize TTS audio.")
parser.add_argument(
"--format",
default="mp3",
choices=["mp3", "wav", "aac", "flac", "opus", "pcm"],
help="Audio output format (default: mp3).",
)
parser.add_argument(
"--voice",
default="nova",
help="TTS voice (default: nova). Try 'alloy', 'verse', etc.",
)
parser.add_argument(
"--model",
default="tts-1-hd",
choices=["tts-1-hd", "gpt-4o-mini-tts"],
help="TTS model: 'tts-1-hd' for high quality, 'gpt-4o-mini-tts' for low latency.",
)
args = parser.parse_args()
main(args.format, args.voice, args.model)