luli331/oppy_google
0
1import io2import os3import struct4 5from google import genai6from google.genai import types7 8 9def _make_wav(pcm_data: bytes, sample_rate: int = 24000, channels: int = 1, bits_per_sample: int = 16) -> bytes:10 """Wrap raw PCM bytes in a WAV container."""11 data_size = len(pcm_data)12 byte_rate = sample_rate * channels * bits_per_sample // 813 block_align = channels * bits_per_sample // 814 15 buf = io.BytesIO()16 # RIFF header17 buf.write(b"RIFF")18 buf.write(struct.pack("<I", 36 + data_size))19 buf.write(b"WAVE")20 # fmt chunk21 buf.write(b"fmt ")22 buf.write(struct.pack("<I", 16)) # chunk size23 buf.write(struct.pack("<H", 1)) # PCM format24 buf.write(struct.pack("<H", channels))25 buf.write(struct.pack("<I", sample_rate))26 buf.write(struct.pack("<I", byte_rate))27 buf.write(struct.pack("<H", block_align))28 buf.write(struct.pack("<H", bits_per_sample))29 # data chunk30 buf.write(b"data")31 buf.write(struct.pack("<I", data_size))32 buf.write(pcm_data)33 return buf.getvalue()34 35 36def generate_speech(text: str) -> bytes:37 """Generate speech audio from text using Gemini TTS.38 39 Args:40 text: The text to convert to speech.41 42 Returns:43 WAV audio bytes ready to play in a browser.44 """45 client = genai.Client(api_key=os.getenv("GOOGLE_API_KEY"))46 47 response = client.models.generate_content(48 model="gemini-2.5-flash-preview-tts",49 contents=text,50 config=types.GenerateContentConfig(51 response_modalities=["AUDIO"],52 speech_config=types.SpeechConfig(53 voice_config=types.VoiceConfig(54 prebuilt_voice_config=types.PrebuiltVoiceConfig(55 voice_name="Kore",56 )57 ),58 ),59 ),60 )61 62 audio_data = response.candidates[0].content.parts[0].inline_data.data63 return _make_wav(audio_data)64 