全模态【Qwen-Omni】:音频+文字输入,生成文本回答+语音回复(基于网上音频URL)
以下代码核心功能如下:
-
音频查询处理
-
读取本地音频文件(支持WAV、MP3、M4A、FLAC格式) -
将音频转换为base64编码并发送给OpenAI模型 -
同时发送文本查询,实现"音频+文本"的多模态交互
-
流式响应处理
-
实时接收AI的文本回复(逐字显示) -
同时接收AI生成的语音回复数据 -
支持实时交互体验
-
多模态输出
-
文本回复:AI对音频内容和文本查询的分析回答 -
语音回复:AI生成的语音响应(使用指定音色)
import os
import base64
import numpy as np
import soundfile as sf
from openai import OpenAI
def process_audio_query(audio_path, query_text, output_audio_path="response_audio.wav", voice="Cherry", model="qwen3-omni-flash"):
"""
处理本地音频查询并返回文本回复和保存音频文件
Args:
audio_path (str): 本地音频文件的路径
query_text (str): 查询文本
output_audio_path (str): 输出音频文件的路径
voice (str): 语音音色
model (str): 使用的模型
Returns:
dict: 包含文本回复和音频文件路径的字典
"""
try:
# 检查本地音频文件是否存在
if not os.path.exists(audio_path):
raise FileNotFoundError(f"音频文件不存在: {audio_path}")
# 获取文件扩展名以确定格式
file_ext = os.path.splitext(audio_path)[1].lower().lstrip('.')
supported_formats = ['wav', 'mp3', 'm4a', 'flac']
if file_ext not in supported_formats:
print(f"警告: 文件格式 '{file_ext}' 可能不被完全支持,尝试使用...")
# 读取本地音频文件并转换为base64
with open(audio_path, "rb") as audio_file:
audio_bytes = audio_file.read()
audio_base64 = base64.b64encode(audio_bytes).decode('utf-8')
print(f"已加载本地音频文件: {audio_path}")
print(f"文件大小: {len(audio_bytes)} 字节")
print(f"格式: {file_ext}")
# 创建聊天补全请求
completion = client.chat.completions.create(
model=model,
messages=[
{
"role": "user",
"content": [
{
"type": "input_audio",
"input_audio": {
"data": f"data:audio/{file_ext};base64,{audio_base64}",
"format": file_ext,
},
},
{"type": "text", "text": query_text},
],
},
],
modalities=["text", "audio"],
audio={"voice": voice, "format": "wav"},
stream=True,
stream_options={"include_usage": True},
)
# 初始化变量来收集响应
collected_text = ""
audio_base64_string = "" # 用于累积音频的base64数据
usage_info = None
print("=== 开始接收响应 ===")
# 处理流式响应
for chunk in completion:
# 处理文本内容
if (chunk.choices and
chunk.choices[0].delta and
chunk.choices[0].delta.content):
text_content = chunk.choices[0].delta.content
collected_text += text_content
print(text_content, end="", flush=True)
# 处理音频数据
if (chunk.choices and
hasattr(chunk.choices[0].delta, "audio") and
chunk.choices[0].delta.audio):
# 从音频数据中获取base64编码的字符串并拼接
audio_data = chunk.choices[0].delta.audio.get("data", "")
if audio_data:
audio_base64_string += audio_data
# 保存使用量信息
if hasattr(chunk, 'usage') and chunk.usage:
usage_info = chunk.usage
# 打印完整的文本回复
print(f"\n\n=== 完整文本回复 ===")
print(collected_text)
# 保存音频文件
if audio_base64_string:
try:
# 将base64字符串解码为字节数据
wav_bytes = base64.b64decode(audio_base64_string)
# 将字节数据转换为numpy数组,使用16位整数格式(WAV标准格式)
audio_np = np.frombuffer(wav_bytes, dtype=np.int16)
# 使用soundfile库将音频数据保存为WAV文件
sf.write(output_audio_path, audio_np, samplerate=24000)
print(f"\n=== 音频回复已保存 ===")
print(f"音频文件: {output_audio_path}")
print(f"文件大小: {len(wav_bytes)} 字节")
print(f"音频采样点数: {len(audio_np)}")
# 验证文件是否成功创建
if os.path.exists(output_audio_path) and os.path.getsize(output_audio_path) > 0:
print("✓ 音频文件保存成功")
else:
print("✗ 音频文件保存失败")
output_audio_path = None
except Exception as audio_error:
print(f"\n音频文件保存失败: {audio_error}")
output_audio_path = None
else:
print(f"\n=== 未接收到音频数据 ===")
output_audio_path = None
# 打印使用量统计信息
if usage_info:
print(f"\n=== 使用量统计 ===")
print(f"Token使用量: {usage_info}")
# 返回结果
return {
"text_response": collected_text,
"audio_file_path": output_audio_path,
"audio_data_size": len(audio_base64_string) if audio_base64_string else 0,
"usage_info": usage_info,
"input_audio_info": {
"file_path": audio_path,
"file_size": len(audio_bytes),
"format": file_ext
}
}
except Exception as e:
print(f"\n=== 发生错误 ===")
print(f"错误信息: {e}")
return {
"text_response": "",
"audio_file_path": None,
"audio_data_size": 0,
"usage_info": None,
"error": str(e)
}
# 辅助函数:检查音频文件信息
def check_audio_file(audio_path):
"""检查音频文件信息"""
if not os.path.exists(audio_path):
print(f"文件不存在: {audio_path}")
return False
file_size = os.path.getsize(audio_path)
file_ext = os.path.splitext(audio_path)[1].lower().lstrip('.')
print(f"音频文件信息:")
print(f" 路径: {audio_path}")
print(f" 大小: {file_size} 字节 ({file_size/1024:.2f} KB)")
print(f" 格式: {file_ext}")
# 尝试读取文件
try:
with open(audio_path, "rb") as f:
data = f.read()
print(f" 可读取: ✓")
return True
except Exception as e:
print(f" 可读取: ✗ ({e})")
return False
示例,本地有一个full_analysis.wav音频文件。
您的浏览器不支持音频元素。
# 使用本地音频文件
local_audio_path = "full_analysis.wav"
query_text = "这段音频在说什么"
output_path = "response_audio.wav"
print("开始处理本地音频查询...")
result = process_audio_query(
audio_path=local_audio_path,
query_text=query_text,
output_audio_path=output_path,
voice="Cherry"
)
print(f"\n=== 处理结果 ===")
print(f"输入音频: {result.get('input_audio_info', {}).get('file_path')}")
print(f"输入大小: {result.get('input_audio_info', {}).get('file_size')} 字节")
print(f"文本回复: {result['text_response']}")
print(f"音频文件: {result['audio_file_path']}")
print(f"音频数据大小: {result['audio_data_size']} 字符")
输出为:
开始处理本地音频查询...
已加载本地音频文件: full_analysis.wav
文件大小: 1486124 字节
格式: wav
=== 开始接收响应 ===
这段音频描述了一幅温馨的海滩画面:夕阳下,一位年轻女子和她的金毛犬在沙滩上互动,狗狗用前爪搭在女子手上,像在击掌。整个场景宁静和谐,展现了人与宠物之间深厚的情感。
=== 完整文本回复 ===
这段音频描述了一幅温馨的海滩画面:夕阳下,一位年轻女子和她的金毛犬在沙滩上互动,狗狗用前爪搭在女子手上,像在击掌。整个场景宁静和谐,展现了人与宠物之间深厚的情感。
=== 音频回复已保存 ===
音频文件: response_audio.wav
文件大小: 848640 字节
音频采样点数: 424320
✓ 音频文件保存成功
=== 使用量统计 ===
Token使用量: CompletionUsage(completion_tokens=274, prompt_tokens=1083, total_tokens=1357, completion_tokens_details=CompletionTokensDetails(accepted_prediction_tokens=None, audio_tokens=221, reasoning_tokens=None, rejected_prediction_tokens=None, text_tokens=53), prompt_tokens_details=PromptTokensDetails(audio_tokens=776, cached_tokens=None, text_tokens=307))
=== 处理结果 ===
输入音频: full_analysis.wav
输入大小: 1486124 字节
文本回复: 这段音频描述了一幅温馨的海滩画面:夕阳下,一位年轻女子和她的金毛犬在沙滩上互动,狗狗用前爪搭在女子手上,像在击掌。整个场景宁静和谐,展现了人与宠物之间深厚的情感。
音频文件: response_audio.wav
音频数据大小: 1131520 字符
您的浏览器不支持音频元素。
批量处理本地文件夹中的音频文件
以下代码的主要功能如下:
批量音频文件处理:该系统能够自动扫描指定文件夹中的所有音频文件,并对每个文件进行统一的AI处理。系统支持多种常见音频格式,包括WAV、MP3、M4A和FLAC等。
智能文件查找:程序会精确匹配文件扩展名,同时兼顾大小写版本,确保不遗漏任何支持的音频文件。找到文件后会自动去重并按文件名排序,保证处理顺序的一致性。
自动化流水线处理:对于找到的每个音频文件,系统会为其生成对应的输出文件名,保持输入输出文件的关联性。然后调用音频处理函数,使用指定的AI模型和语音音色进行处理。
灵活查询配置:系统提供了一个辅助函数,可以根据不同的配置方式为不同文件设置不同的查询文本。支持字符串统一查询、字典模式匹配和列表精确匹配三种配置方式。
完善的结果处理:每个文件处理完成后,系统会记录详细的结果信息,包括输入文件路径、文本回复、生成的音频文件路径等。如果处理过程中出现错误,会捕获异常并记录错误信息。
生成详细报告:处理完成后,系统会自动生成一份详细的处理报告,记录每个文件的处理状态、成功失败统计、成功率等信息。报告以文本文件形式保存,方便用户查看整体处理情况。
import os
import glob
from typing import List, Dict, Any
def batch_process_local_audio_folder(input_folder, query_text, output_dir="audio_outputs",
voice="Cherry", model="qwen3-omni-flash",
audio_extensions=None):
"""
批量处理本地文件夹中的音频文件
Args:
input_folder (str): 包含音频文件的输入文件夹路径
query_text (str): 对所有音频文件的统一查询文本
output_dir (str): 输出目录
voice (str): 语音音色
model (str): 使用的模型
audio_extensions (list): 支持的音频文件扩展名,默认为['.wav', '.mp3', '.m4a', '.flac']
Returns:
list: 包含每个音频文件处理结果的列表
"""
if audio_extensions is None:
audio_extensions = ['.wav', '.mp3', '.m4a', '.flac']
# 创建输出目录
os.makedirs(output_dir, exist_ok=True)
# 更精确地查找音频文件
audio_files = []
for ext in audio_extensions:
# 使用精确的文件扩展名匹配
pattern = os.path.join(input_folder, f"*{ext}")
found_files = glob.glob(pattern)
audio_files.extend(found_files)
# 同时查找大写扩展名版本
pattern_upper = os.path.join(input_folder, f"*{ext.upper()}")
found_files_upper = glob.glob(pattern_upper)
audio_files.extend(found_files_upper)
# 去重(避免因为大小写重复)
audio_files = list(set(audio_files))
# 按文件名排序,确保处理顺序一致
audio_files.sort()
if not audio_files:
print(f"在文件夹 '{input_folder}' 中未找到音频文件")
print(f"支持的格式: {', '.join(audio_extensions)}")
return []
print(f"找到 {len(audio_files)} 个音频文件:")
for i, file_path in enumerate(audio_files, 1):
file_size = os.path.getsize(file_path)
print(f" {i}. {os.path.basename(file_path)} ({file_size/1024:.1f} KB)")
# 调试信息:显示实际找到的文件
print(f"\n实际文件列表:")
for file_path in audio_files:
print(f" - {file_path}")
results = []
for i, audio_file in enumerate(audio_files, 1):
print(f"\n{'='*50}")
print(f"处理第 {i}/{len(audio_files)} 个文件: {os.path.basename(audio_file)}")
print(f"{'='*50}")
# 生成输出文件名(基于输入文件名)
input_filename = os.path.splitext(os.path.basename(audio_file))[0]
output_filename = f"response_{input_filename}.wav"
output_path = os.path.join(output_dir, output_filename)
try:
result = process_audio_query(
audio_path=audio_file,
query_text=query_text,
output_audio_path=output_path,
voice=voice,
model=model
)
# 添加输入文件信息到结果中
result["input_file"] = audio_file
result["input_filename"] = os.path.basename(audio_file)
results.append(result)
except Exception as e:
print(f"处理文件 {audio_file} 时发生错误: {e}")
error_result = {
"input_file": audio_file,
"input_filename": os.path.basename(audio_file),
"text_response": "",
"audio_file_path": None,
"audio_data_size": 0,
"usage_info": None,
"error": str(e)
}
results.append(error_result)
return results
def get_query_for_file(filename, queries_config):
"""
根据文件名和查询配置获取对应的查询文本
"""
if isinstance(queries_config, str):
# 如果是字符串,直接返回
return queries_config
elif isinstance(queries_config, dict):
# 如果是字典,按文件名模式匹配
for pattern, query in queries_config.items():
if pattern in filename:
return query
# 如果没有匹配,返回第一个查询
return list(queries_config.values())[0]
elif isinstance(queries_config, list):
# 如果是列表,查找对应的文件名
for item in queries_config:
if item.get("filename") == filename:
return item.get("query", "这段音频在说什么")
# 如果没有匹配,返回第一个查询
return queries_config[0].get("query", "这段音频在说什么")
else:
return "这段音频在说什么"
def generate_summary_report(results, output_dir="audio_outputs"):
"""
生成批量处理的总结报告
Args:
results (list): 批量处理的结果列表
output_dir (str): 输出目录
Returns:
dict: 处理统计信息
"""
successful = 0
failed = 0
total_files = len(results)
report_file = os.path.join(output_dir, "processing_report.txt")
with open(report_file, "w", encoding="utf-8") as f:
f.write("音频文件批量处理报告\n")
f.write("=" * 50 + "\n\n")
for i, result in enumerate(results, 1):
f.write(f"文件 {i}: {result.get('input_filename', '未知文件')}\n")
f.write(f"输入路径: {result.get('input_file', '未知')}\n")
if result.get('error'):
f.write(f"状态: 失败 - {result['error']}\n")
failed += 1
else:
f.write(f"状态: 成功\n")
f.write(f"文本回复: {result.get('text_response', '')}\n")
f.write(f"输出音频: {result.get('audio_file_path', '无')}\n")
successful += 1
f.write("-" * 30 + "\n\n")
f.write(f"处理总结:\n")
f.write(f"总文件数: {total_files}\n")
f.write(f"成功: {successful}\n")
f.write(f"失败: {failed}\n")
f.write(f"成功率: {successful/total_files*100:.1f}%\n")
print(f"\n处理报告已保存至: {report_file}")
return {
"total_files": total_files,
"successful": successful,
"failed": failed,
"success_rate": successful/total_files*100,
"report_file": report_file
}
批量处理示例,在audio_inputs文件夹中有两个音频文件:
您的浏览器不支持音频元素。
您的浏览器不支持音频元素。
"""批量处理示例"""
# 示例1: 统一查询所有音频文件
print("示例1: 统一查询所有音频文件")
results1 = batch_process_local_audio_folder(
input_folder="./audio_inputs", # 输入文件夹路径
query_text="这段音频在说什么", # 对所有文件的统一查询
output_dir="./batch_outputs", # 输出文件夹
voice="Cherry"
)
# 生成报告
stats1 = generate_summary_report(results1, "./batch_outputs")
print(f"处理完成: {stats1['successful']}/{stats1['total_files']} 成功")
输出为:
示例1: 统一查询所有音频文件
找到 2 个音频文件:
1. audio_assistant.wav (521.3 KB)
2. eagle_analysis.wav (528.8 KB)
实际文件列表:
- ./audio_inputs\audio_assistant.wav
- ./audio_inputs\eagle_analysis.wav
==================================================
处理第 1/2 个文件: audio_assistant.wav
==================================================
已加载本地音频文件: ./audio_inputs\audio_assistant.wav
文件大小: 533804 字节
格式: wav
=== 开始接收响应 ===
这段音频是通义实验室的多模态超大规模语言模型Qwen-Omni的自我介绍。它说明了自己是阿里巴巴集团旗下的通义实验室自主研发的,然后询问对方有什么需要帮助的。
=== 完整文本回复 ===
这段音频是通义实验室的多模态超大规模语言模型Qwen-Omni的自我介绍。它说明了自己是阿里巴巴集团旗下的通义实验室自主研发的,然后询问对方有什么需要帮助的。
=== 音频回复已保存 ===
音频文件: ./batch_outputs\response_audio_assistant.wav
文件大小: 622080 字节
音频采样点数: 311040
✓ 音频文件保存成功
=== 使用量统计 ===
Token使用量: CompletionUsage(completion_tokens=207, prompt_tokens=587, total_tokens=794, completion_tokens_details=CompletionTokensDetails(accepted_prediction_tokens=None, audio_tokens=162, reasoning_tokens=None, rejected_prediction_tokens=None, text_tokens=45), prompt_tokens_details=PromptTokensDetails(audio_tokens=280, cached_tokens=None, text_tokens=307))
==================================================
处理第 2/2 个文件: eagle_analysis.wav
==================================================
已加载本地音频文件: ./audio_inputs\eagle_analysis.wav
文件大小: 541484 字节
格式: wav
=== 开始接收响应 ===
这段音频在描述一只白头海雕的外貌特征。它说这只鸟头部和尾部是白色的,身体和翅膀是深棕色的,有黄色的喙和爪子,看起来很威武。
=== 完整文本回复 ===
这段音频在描述一只白头海雕的外貌特征。它说这只鸟头部和尾部是白色的,身体和翅膀是深棕色的,有黄色的喙和爪子,看起来很威武。
=== 音频回复已保存 ===
音频文件: ./batch_outputs\response_eagle_analysis.wav
文件大小: 641280 字节
音频采样点数: 320640
✓ 音频文件保存成功
=== 使用量统计 ===
Token使用量: CompletionUsage(completion_tokens=213, prompt_tokens=591, total_tokens=804, completion_tokens_details=CompletionTokensDetails(accepted_prediction_tokens=None, audio_tokens=167, reasoning_tokens=None, rejected_prediction_tokens=None, text_tokens=46), prompt_tokens_details=PromptTokensDetails(audio_tokens=284, cached_tokens=None, text_tokens=307))
处理报告已保存至: ./batch_outputs\processing_report.txt
处理完成: 2/2 成功
将在batch_outputs文件夹生成一个txt和两个音频文件。
以下代码进行批量处理本地文件夹中的音频文件,每个文件可以使用不同的查询文本。主要功能如下:
智能批量音频处理:该函数能够自动扫描指定文件夹中的所有音频文件,并为每个文件应用不同的查询文本进行处理。它支持多种音频格式,包括常见的WAV、MP3、M4A、FLAC等格式,同时兼顾大小写版本的文件扩展名。
灵活的查询配置系统:这是该函数的主要特色,它允许用户为不同的音频文件设置不同的查询问题。查询配置支持两种方式:字典配置允许通过文件名模式匹配查询文本,列表配置则支持为每个具体文件指定精确的查询内容。系统会根据配置自动为每个文件分配合适的查询文本。
自动化处理流程:函数会自动创建输出目录,扫描输入文件夹中的音频文件,进行去重和排序,然后逐个处理每个文件。对于每个音频文件,它会生成对应的输出文件名,调用底层的音频处理函数,并记录详细的处理结果。
完善的错误处理和结果追踪:处理过程中会捕获并记录任何异常,确保单个文件的失败不会影响整个批处理流程。每个处理结果都包含输入文件信息、使用的查询文本、文本回复、生成的音频文件路径等详细信息,便于后续分析和调试。
实时进度反馈:在处理过程中,函数会实时显示当前处理的文件进度、文件名以及使用的查询文本,让用户清晰了解处理状态。
def batch_process_audio_queries_with_custom_queries(input_folder, queries_config, output_dir="audio_outputs",
voice="Cherry", model="qwen3-omni-flash"):
"""
批量处理本地文件夹中的音频文件,每个文件可以使用不同的查询文本
Args:
input_folder (str): 包含音频文件的输入文件夹路径
queries_config (dict or list): 查询配置
- 如果是dict: {文件名模式: 查询文本}
- 如果是list: [{"filename": 文件名, "query": 查询文本}]
output_dir (str): 输出目录
voice (str): 语音音色
model (str): 使用的模型
Returns:
list: 包含每个音频文件处理结果的列表
"""
os.makedirs(output_dir, exist_ok=True)
# 查找所有音频文件
audio_extensions = ['.wav', '.mp3', '.m4a', '.flac', '.WAV', '.MP3', '.M4A', '.FLAC']
# 更精确地查找音频文件
audio_files = []
for ext in audio_extensions:
# 使用精确的文件扩展名匹配
pattern = os.path.join(input_folder, f"*{ext}")
found_files = glob.glob(pattern)
audio_files.extend(found_files)
# 同时查找大写扩展名版本
pattern_upper = os.path.join(input_folder, f"*{ext.upper()}")
found_files_upper = glob.glob(pattern_upper)
audio_files.extend(found_files_upper)
# 去重(避免因为大小写重复)
audio_files = list(set(audio_files))
# 按文件名排序,确保处理顺序一致
audio_files.sort()
if not audio_files:
print(f"在文件夹 '{input_folder}' 中未找到音频文件")
print(f"支持的格式: {', '.join(audio_extensions)}")
return []
print(f"找到 {len(audio_files)} 个音频文件:")
for i, file_path in enumerate(audio_files, 1):
file_size = os.path.getsize(file_path)
print(f" {i}. {os.path.basename(file_path)} ({file_size/1024:.1f} KB)")
# 调试信息:显示实际找到的文件
print(f"\n实际文件列表:")
for file_path in audio_files:
print(f" - {file_path}")
results = []
for i, audio_file in enumerate(audio_files, 1):
filename = os.path.basename(audio_file)
# 根据配置类型获取查询文本
query_text = get_query_for_file(filename, queries_config)
print(f"\n处理第 {i}/{len(audio_files)} 个文件: {filename}")
print(f"查询: {query_text}")
# 生成输出文件名
input_filename = os.path.splitext(filename)[0]
output_filename = f"response_{input_filename}.wav"
output_path = os.path.join(output_dir, output_filename)
try:
result = process_audio_query(
audio_path=audio_file,
query_text=query_text,
output_audio_path=output_path,
voice=voice,
model=model
)
result["input_file"] = audio_file
result["input_filename"] = filename
result["query_used"] = query_text
results.append(result)
except Exception as e:
print(f"处理文件 {filename} 时发生错误: {e}")
error_result = {
"input_file": audio_file,
"input_filename": filename,
"query_used": query_text,
"text_response": "",
"audio_file_path": None,
"audio_data_size": 0,
"usage_info": None,
"error": str(e)
}
results.append(error_result)
return results
# 示例2: 不同文件使用不同查询
print("\n示例2: 不同文件使用不同查询")
queries_config = {
"audio_assistant": "总结这段录音的内容",
"eagle_analysis": "音频介绍了什么动物"
}
results2 = batch_process_audio_queries_with_custom_queries(
input_folder="./audio_inputs",
queries_config=queries_config,
output_dir="./custom_outputs"
)
stats2 = generate_summary_report(results2, "./custom_outputs")
print(f"处理完成: {stats2['successful']}/{stats2['total_files']} 成功")
输出为:
示例2: 不同文件使用不同查询
找到 2 个音频文件:
1. audio_assistant.wav (521.3 KB)
2. eagle_analysis.wav (528.8 KB)
实际文件列表:
- ./audio_inputs\audio_assistant.wav
- ./audio_inputs\eagle_analysis.wav
处理第 1/2 个文件: audio_assistant.wav
查询: 总结这段录音的内容
已加载本地音频文件: ./audio_inputs\audio_assistant.wav
文件大小: 533804 字节
格式: wav
=== 开始接收响应 ===
我是通义千问Omni,阿里巴巴集团通义实验室自主研发的多模态超大规模语言模型,有什么我可以帮助你的吗?
=== 完整文本回复 ===
我是通义千问Omni,阿里巴巴集团通义实验室自主研发的多模态超大规模语言模型,有什么我可以帮助你的吗?
=== 音频回复已保存 ===
音频文件: ./custom_outputs\response_audio_assistant.wav
文件大小: 426240 字节
音频采样点数: 213120
✓ 音频文件保存成功
=== 使用量统计 ===
Token使用量: CompletionUsage(completion_tokens=140, prompt_tokens=587, total_tokens=727, completion_tokens_details=CompletionTokensDetails(accepted_prediction_tokens=None, audio_tokens=111, reasoning_tokens=None, rejected_prediction_tokens=None, text_tokens=29), prompt_tokens_details=PromptTokensDetails(audio_tokens=280, cached_tokens=None, text_tokens=307))
处理第 2/2 个文件: eagle_analysis.wav
查询: 音频介绍了什么动物
已加载本地音频文件: ./audio_inputs\eagle_analysis.wav
文件大小: 541484 字节
格式: wav
=== 开始接收响应 ===
音频介绍的是一只白头海雕。
=== 完整文本回复 ===
音频介绍的是一只白头海雕。
=== 音频回复已保存 ===
音频文件: ./custom_outputs\response_eagle_analysis.wav
文件大小: 122880 字节
音频采样点数: 61440
✓ 音频文件保存成功
=== 使用量统计 ===
Token使用量: CompletionUsage(completion_tokens=42, prompt_tokens=591, total_tokens=633, completion_tokens_details=CompletionTokensDetails(accepted_prediction_tokens=None, audio_tokens=32, reasoning_tokens=None, rejected_prediction_tokens=None, text_tokens=10), prompt_tokens_details=PromptTokensDetails(audio_tokens=284, cached_tokens=None, text_tokens=307))
处理报告已保存至: ./custom_outputs\processing_report.txt
处理完成: 2/2 成功
将在custom_outputs文件夹生成一个txt和两个音频文件。
您的浏览器不支持音频元素。
您的浏览器不支持音频元素。

