# To run this code you need to install the following dependencies:
# pip install google-genai
import base64
import mimetypes
import os
import re
import struct
from google import genai
from [Link] import types
def save_binary_file(file_name, data):
f = open(file_name, "wb")
[Link](data)
[Link]()
print(f"File saved to to: {file_name}")
def generate():
client = [Link](
api_key=[Link]("GEMINI_API_KEY"),
)
model = "gemini-2.5-pro-preview-tts"
contents = [
[Link](
role="user",
parts=[
[Link].from_text(text="""¿Cómo un simple teléfono pudo causar millones de
muertes?. Este aparato, color rojo sangre, fue utilizado para dar órdenes mortales durante
la Segunda Guerra Mundial. Perteneció a Adolf Hitler y fue recuperado de su búnker
personal tras su caída. Décadas después, fue subastado en el año 2017 por más de 240 mil
dólares... Una reliquia tan valiosa como escalofriante. Es… fascinante."""),
],
),
]
generate_content_config = [Link](
temperature=1,
response_modalities=[
"audio",
],
speech_config=[Link](
voice_config=[Link](
prebuilt_voice_config=[Link](
voice_name="Enceladus"
)
)
),
)
file_index = 0
for chunk in [Link].generate_content_stream(
model=model,
contents=contents,
config=generate_content_config,
):
if (
[Link] is None
or [Link][0].content is None
or [Link][0].[Link] is None
):
continue
if [Link][0].[Link][0].inline_data and
[Link][0].[Link][0].inline_data.data:
file_name = f"ENTER_FILE_NAME_{file_index}"
file_index += 1
inline_data = [Link][0].[Link][0].inline_data
data_buffer = inline_data.data
file_extension = mimetypes.guess_extension(inline_data.mime_type)
if file_extension is None:
file_extension = ".wav"
data_buffer = convert_to_wav(inline_data.data, inline_data.mime_type)
save_binary_file(f"{file_name}{file_extension}", data_buffer)
else:
print([Link])
def convert_to_wav(audio_data: bytes, mime_type: str) -> bytes:
"""Generates a WAV file header for the given audio data and parameters.
Args:
audio_data: The raw audio data as a bytes object.
mime_type: Mime type of the audio data.
Returns:
A bytes object representing the WAV file header.
"""
parameters = parse_audio_mime_type(mime_type)
bits_per_sample = parameters["bits_per_sample"]
sample_rate = parameters["rate"]
num_channels = 1
data_size = len(audio_data)
bytes_per_sample = bits_per_sample // 8
block_align = num_channels * bytes_per_sample
byte_rate = sample_rate * block_align
chunk_size = 36 + data_size # 36 bytes for header fields before data chunk size
# [Link]
header = [Link](
"<4sI4s4sIHHIIHH4sI",
b"RIFF", # ChunkID
chunk_size, # ChunkSize (total file size - 8 bytes)
b"WAVE", # Format
b"fmt ", # Subchunk1ID
16, # Subchunk1Size (16 for PCM)
1, # AudioFormat (1 for PCM)
num_channels, # NumChannels
sample_rate, # SampleRate
byte_rate, # ByteRate
block_align, # BlockAlign
bits_per_sample, # BitsPerSample
b"data", # Subchunk2ID
data_size # Subchunk2Size (size of audio data)
)
return header + audio_data
def parse_audio_mime_type(mime_type: str) -> dict[str, int | None]:
"""Parses bits per sample and rate from an audio MIME type string.
Assumes bits per sample is encoded like "L16" and rate as "rate=xxxxx".
Args:
mime_type: The audio MIME type string (e.g., "audio/L16;rate=24000").
Returns:
A dictionary with "bits_per_sample" and "rate" keys. Values will be
integers if found, otherwise None.
"""
bits_per_sample = 16
rate = 24000
# Extract rate from parameters
parts = mime_type.split(";")
for param in parts: # Skip the main type part
param = [Link]()
if [Link]().startswith("rate="):
try:
rate_str = [Link]("=", 1)[1]
rate = int(rate_str)
except (ValueError, IndexError):
# Handle cases like "rate=" with no value or non-integer value
pass # Keep rate as default
elif [Link]("audio/L"):
try:
bits_per_sample = int([Link]("L", 1)[1])
except (ValueError, IndexError):
pass # Keep bits_per_sample as default if conversion fails
return {"bits_per_sample": bits_per_sample, "rate": rate}
if __name__ == "__main__":
generate()