Public Docs
【模型量化】深度学习模型量化 & 量化理论 & 各平台的量化过程 & 硬件加速
【TVM】TI关于TVM的使用测试与分析
【LLM&LVM】大模型开源工程思维导图
SmartSip
【北航卓越工程师】《汽车前沿技术导论:智能驾驶》讲义
【工具链】Yocto使用介绍——使用Yocto创建一个树莓派的系统镜像
【工具链】使用ssh+dialog指令设定服务器指定用户仅容器访问
【推理引擎】一篇关于模型推理的详细对比与学习
【推理引擎】关于TVM中的Schedule优化详解(On going)
【LLM微调】使用litgpt进行私有数据集模型微调的测试总结
【TVM】在TVM Relay中创建一个自定义操作符
【STT+LLM+TTS】如何使用语音转文字模型+大预言模型+语音生成模型完成一个类人的语音交互机器人
【RAG】 通过RAG构建垂直领域的LLM Agent的方法探索
【RAG】GraphRAG精读与测试(On going)
【AI Agent】MetaGPT精读与学习
【AI Base】Ilya Sutskever 27篇必读论文分享清单
【Nvidia】Jetson AGX Orin/ Jetson Orin nano 硬件测试调试内容(On going)
【BI/DI】LLM Using in BI Testing Scenario (On going)
【Nvidia】How to Activate a Camera on Nvidia Platform in Details
【RAS-PI】树莓派驱动开发
【行业咨询阅读】关注实时咨询和分析
【mobileye】2024 Driving AI
【mobileye】SDS_Safety_Architecture
【yolo】yolov8测试
【nvidia】Triton server实践
【alibaba】MNN(on updating)
【OpenAI】Triton(on updating)
【CAIS】关于Compound AI Systems的思考
【Nvidia】关于Cuda+Cudnn+TensorRT推理环境
【BEV】BEVDet在各个平台上的执行效率及优化(On Updating)
【Chip】AI在芯片设计和电路设计中的应用
【Chip】ChiPFormer
【Chip】关于布线的学习
【Chip】MaskPlace论文精读与工程复现优化
【gynasium】强化学习初体验
【Cadence】X AI
【transformer】MinGPT开源工程学习
【中间件】针对apollo 10.0中关于cyberRT性能优化的深度解读和思考
【Robotics】调研了解当前机器人开发者套件(on updating)
【Robotics】ROS CON China 2024 文档技术整理与感想总结(上2024.12.7,中2024.12.8,下场外产品)
【algorithm】关于模型、数据与标注规范的平衡问题
【nvidia】DLA的学习了解与使用
【nvidia】构建nvidia嵌入式平台的交叉编译环境(其他环境平台可借鉴)
【2025AI生成式大会】2025大会个人总结
【Robotics】 Create Quadruped Robot RL FootStep Training Environment In IsaacLab
【Robotics】如何一个人较为完整的完成一个机器人系统软件算法层面的设计与开发
【VLM】读懂多模态大模型评价指标
【VLM】大模型部署的端侧部署性能与精度评估方法与分析
【Nvidia】Jetson Orin 平台VLM部署方法与指标评测
【Database】向量数据库
【SoC】性能与功耗评估
【MCP】MCP探索
【InnoFrance】一个“关于声音”的有趣项目
文档发布于【Feng's Docs】
-
+
首页
【InnoFrance】一个“关于声音”的有趣项目
# 0 PreTalk 通过AI手段构建一个用来自主、持续生成高质量内容的播客的工作流或智能体,是InnoFrance项目的主要目的。作为播客的重度听众,每年收听上千小时的优质播客内容,对我们来说并不是负担或者是消磨时间的方式,而是能从多元化的播客内容中获得思想的碰撞与认知的进化。 随着近些年AI技术的不断迭代,越来越多的播客内容开始以AI为主体而呈现,例如播客的声音、文稿摘要与总结、文稿内容优化等等。作为听众,虽然相关内容仍有瑕疵,但是也切实感受到不少优质的内容和呈现方式,可以让人忽略音频中夹杂的磕绊与错乱。并在持续的关注与收听中感受到制作的进步。 作为播客内容的受益者,我们也希望通过对于当前AI技术的理解,形成一套自己的内容输出技术方案,使得大家可以借助我们的经验,在尽可能低的生产成本下不断输出高质量、多元化的播客内容。整个方案我们会在不断调优后开源! 而播客的选题首先是满足我们自己,如果我们自己本身不能作为内容的受众,那也可能很难让其他听众产生共鸣。最终我们将“法兰西科技创新第一现场”作为我们打磨技术的内容载体。 `所以,InnoFrance的主要项目目标,是开发一个内容生产Agentic工具平台。` ## 0.1 法兰西科技创新第一现场播客简介 `《法兰西科技创新第一现场》是调试InnoFrance项目的第一个内容载体`,如果整个工具平台无法在一个垂类场景完成高质量的内容制作,那整个平台也无法称为合格。 内容简介: https://www.xiaoyuzhoufm.com/podcast/696b79dd1cf4df1532705e36 我们是两名拥有留法背景的计算机工程师。在法国求学、工作和生活的岁月里,那里的文化与教育体系不仅塑造了我们的职业技能,更深刻地重构了我们的思维方式。 虽已回国十余年,但我们与法国的联系从未中断。在当今世界,科技竞争的聚光灯似乎总是打在中美两国身上,许多人认为欧洲因监管严格,正逐渐在AI等未来领域失去话语权。 但我们看到的,是另一个截然不同的欧洲。在这片拥有深厚人文底蕴的大陆上,其实涌动着许多独特的科技思潮与深度观点,只是往往被语言的围墙挡在了中文视野之外。 这正是我们创办这档播客的初衷。我们希望利用最新的AI智能体与大语言模型技术,化身为一座桥梁,将法语世界那些被遗漏的真知灼见,翻译并转化为中文听众触手可及的内容。我们更希望作为一个观察者,带大家看看那些骨子里透着骄傲的欧洲人,将如何面对变革,走出属于自己的路。 欢迎来到这里,让我们一起跨越语言,解读技术背后的文化灵魂。 ## 0.2 好播客的基础元素 笔者自己通过对上百个播客的仔细研究发现,吸引听众的播客频道一般具备一些典型的特质。 - 对于人声播客而言: - 主播的个人特质鲜明,节目主题突出,并能输出较为丰富的观点。 - 在熟悉领域持续深耕,提供高质量内容。 - 邀请有思想深度的嘉宾进行对话,围绕一个或多个主题深挖故事和冲突,并展开深度的思想碰撞 - 拥有一段有代表性的片头曲和片尾曲,增强辨识度。 - 提供清晰的播客简介和重点内容摘要,方便听众快速了解。 - 而对于AI播客来说: - 内容应具备一定的实时性和前瞻性(例如,Hugging Face每日论文总结、AI前沿动态等)。 - 能够高效地总结密集信息或消除语言障碍(例如,跨国串门儿计划)。 - 提供清晰的播客摘要(外文内容需附带原视频链接)和重点内容总结。 - 尽量减少不自然的错误,甚至能还原语调、语气,并复刻情感表达。 播客的受众一方面受限于当前的播客市场,另一方面也因内容主题而异。很少有播客能做到像“半拿铁”那样老少皆宜、广受喜爱。因此,选择一个合适的主题,能让一部分听众觉得有所收获,就已经具有巨大的价值。未来,可以通过智能体工作流的迭代,不断创作出新的题材。 ## 0.3 文章导读目录 整个文章将围绕InnoFrance项目的开发展开详细的说明。 包含目标定义、产品设计、各个模块开发的技术点介绍、工作流编排、系统整合等展开详细的介绍。一方面作为播客内容的听众,了解内容制作的整个流程。作为开发者,可以参考整个InnoFrance项目的设计和开发介绍,完成自己的播客内容或者创意实现。 - 方案设计与整体规划 - 各个子模块的设计与开发,技术点描述与问题记录与解决 - 模块测试与工具使用流程介绍 - 播客内容选型方向介绍 - Annexe:使用到和未使用的一些方案的总结与分析 - 背后故事 # 1 方案设计 - 尝试搜索了一些端到端的方案,但是从目前情况来看,想要完场1-2小时的长播客转录,直接通过多模态大模型端到端的实现还有这不少难度和挑战 - 语音合成目前SOTA版本的错误率也是10分钟 错字率3%左右量级(qwen3-tts),higgs-audio在qwen3-tts未发布之前综合表现也堪称惊艳,可是对于大模型audo-regressive范式,随着生成越来越长,错误变多的情况,还是需要通过一些工程化手段去解决1-2小时量级的音频生成质量的问题; - 针对以上分析的播客节目,整个流程需要能够完成说话人声纹描述、shownote文字稿、时间线以及clone的整个中文音频四部分;而过程产物还包括原文文字稿、翻文文字稿和摘要音频文字稿三部分,所以共7个产物。这些产物的留存和分段,一方面可以用来分析各个过程的生成质量,必要时可以通过平台的易用性交互实现对部分产物的优化,一方面拆分手段方便各个环节在技术手段迭代时易于组装和切换 - 整个过程不论是按照固定工作流编排、本地调试易用性还是通过mcp server方式暴露(可用于目前大模型的能力调用),都是有必要的 - 整体方案设计最终的流程图如下:  # 2 功能开发 ## 2.0 自主内容获取智能体【On going】 自主内容提取智能体的设计是整个工程中比较难的一部分,因为如果要完成一个真正自主内容获取的智能体它需要包含以下几个核心环节: - 具备搜索能力:如果是随意搜索他可能要像人一样具备、检索查找总结概括的能力,这样的能力要求更像是一个通用智能体,还有一个方式是可以基于一些已经明确的目标链接,通过爬虫技术借助RSS或者sitemap的手段进行搜索和整合。这个过程除了需要实现基础的爬虫功能外,可能还需要添加一些关键词,或者向量化匹配手段找到合适的内容; - 具备自主能力:自主能力这里说的不是像agentic系统一样具备自主规划、自主执行的能力,这种方式难度较大。而更多是只主动能力,这里的主动能力从目前已有的工程实现方式来说可以分为以下6种:事件驱动(Event-driven)、定时调度(Scheduler / Cron)、条件触发(Condition-based Trigger)、任务队列 + Worker 自驱动(任务产生 → 入队 → Worker 自动消费)、状态机 / 流程驱动执行(任务状态 → 状态流转 → 下一步自动执行)、监控 + 自触发(Self-triggering System, 监控 → 判断异常 / 机会 → 自动触发任务) - 具备整合总结能力:将索索的信息按照指定要求和格式进行总结 - 具备信息匹配能力:按照指定关键词和内容将匹配度高的结果反馈 基于当前的任务,可以按照如下技术方案执行开发: 1. 按照每天固定时间触发完成智能体自主执行的框架; 2. 按照指定链接触发整体流程; 这部分的实现可以依托于大模型的整合能力,增加生产效率,前期可以先基于人工筛选后的指定链接完成全部流程; ## 2.1 youtube视频转音频智能体【DONE】 不少高质量的内容可能只有视频内容,所以该模块可以用于youtube视频的音频提取,详细使用内容见工程文档。 https://github.com/FengD/InnoFranceYTAudioExtractor  ## 2.2 说话人声纹分析与描述【DONE】 说话人声纹特性实际上是个相对复杂的过程。 目前在大模型的TTS生成过程中,“捏”出来的声音需要提供说话人的性别、年龄、职业、语速、声线特质等等信息的文字描述,而不同语言的人在说话发音时又呈现出一定差异,想将这些特质按照声纹直接翻译为文字描述,再通过大模型“捏出对应声音难度极大”。 虽然像Higgs-audio或者Qwen-TTS这种都支持声音clone且还原度极高,但是使用外国人的声线讲中文,就会有一种带有外国口音的中文的感觉,虽然极大的展现出了clone声音的还原度,但是极大影响了中文听众对内容的听感。 例如,如下两个音频是川子的clone声音讲的中、英文版本的内容,还原度极高,但是中文表达内容很难让听众长时间保持专注力(讲个段子还行)。 中文: [【附件】donald_zh.wav](/media/attachment/2026/02/donald_zh.wav) 英文: [【附件】donald_en.wav](/media/attachment/2026/02/donald_en.wav) 所以最终达到的技术效果还是应该是声线类似,但是内容完全是中国人说普通话的表达。 `后来选择了一个比较tricky的方法。在工程执行过程中发现了一些问题,最终经过一些尝试和分析得到了一个较好的效果。` 对于说话人声纹的分析,如果只是做性别区分,直接基于声纹训练一个小的分类网络 Gender Classifier(ECAPA)是个比较好的做法,但是无法对于说话人的声纹进行自研语言的描述,会有一些影响声音合成的质量和自动化效果。从这一点出发,借助文本语音大模型其实是个比较好的办法。自然而然想到了一些用来做声音理解的模型。 其他例如qwen-audio,kimi-audio,baichuan,step-audio等。因为kimi给了详细指标对比,因为目前是sota级别,所以就先尝试了kimi。事实上是先尝试了qwen2-audio,但是效果不太好(后来发现是方法的问题)。 Qwen-Audio:https://huggingface.co/Qwen/Qwen2-Audio-7B-Instruct Kimi-Audio:https://huggingface.co/moonshotai/Kimi-Audio-7B-Instruct  - 最开始的方案是直接给模型一整段的音频,他需要自己去做多人声分离和识别描述,结果发现效果很差,很难做到性别,声纹和人数的准确基本是以猜为主。提示词如下。后来经过分析发现,Kimi‑Audio 并不是一个“可靠的说话人识别 / 性别识别模型,无法精确区分音色相近的多个说话人,和在无时间边界的情况下统计speaker 数量。模型结构层面 Kimi‑Audio 并没有 diarization 这一层结构性能力。 ``` 你将收到一段包含一位或多位说话人的音频。 请你识别音频中的所有不同说话人,并按他们第一次出现的顺序编号为: [SPEAKER0], [SPEAKER1], [SPEAKER2] ... 请为每一位说话人输出一个 JSON 对象,并严格遵守以下字段定义: 1. speaker_tag - 说话人的唯一标识,如 "[SPEAKER0]" 2. design_text - 描述【这个说话人在内容中的身份或职责】 - 例如:主持人、技术讲解者、嘉宾、提问者 - 不要包含任何声音、音色、语速相关描述 3. design_instruct - 描述【这个说话人的声音特征】,用于声音建模或模仿 - 必须包含:性别、年龄范围、语速、音色或声纹特征 - 可以补充职业气质或性格特征 - 不要描述内容职责 4. language - 用来作为后续功能使用 - 只能是 Chinese 请严格只输出 JSON 数组,不要输出任何额外说明或文字。 样例如下 [ { "speaker_tag": "[SPEAKER0]", "design_text": "第一位说话人,负责整体内容的讲解和信息传达。", "design_instruct": "中年女性声音,年龄约40岁,语速平缓,声音柔和细腻,语调平稳,带有成熟女性的温和与理性气质。", "language": "Chinese" } ] ``` - 所以,想到了以下方案经过测试,效果较好。那就是利用本身文稿和多人声分离部分完成的功能,直接将需要识别的人声保存为指定片段,而直接将有且只有一个声音的声音片段作为模型的输入,再配合提示词的调整,模型对于单个人声的理解和分析准确度较好。 ``` 你将收到一段只包含一位说话人的声音片段. 请为这位说话人输出一个 JSON 对象,并严格遵守以下字段定义: 1. design_text - 描述【这个说话人在内容中的身份或职责】 - 例如:主持人、技术讲解者、嘉宾、提问者 - 不要包含任何声音、音色、语速相关描述 2. design_instruct - 描述【这个说话人的声音特征】,用于声音建模或模仿 - 必须包含:性别、年龄范围、语速、音色或声纹特征 - 可以补充职业气质或性格特征 - 不要描述内容职责 请严格只输出 JSON 数组,不要输出任何额外说明或文字。 样例如下 [ { "design_text": "", "design_instruct": "", } ] ``` - 测试用的代码如下 ``` import json from kimia_infer.api.kimia import KimiAudio # --- 1. Load Model --- model_path = "/data/hehe/Kimi-Audio-7B-Instruct/" model = KimiAudio(model_path=model_path, load_detokenizer=False) # --- 2. Sampling Parameters(偏保守,防止乱编) --- sampling_params = { "text_temperature": 0.1, "text_top_k": 5, "text_repetition_penalty": 1.0, "text_repetition_window_size": 16, } # --- 3. Prompt --- prompt = """ 你将收到一段只包含一位说话人的声音片段. 请为这位说话人输出一个 JSON 对象,并严格遵守以下字段定义: 1. design_text - 描述【这个说话人在内容中的身份或职责】 - 例如:主持人、技术讲解者、嘉宾、提问者 - 不要包含任何声音、音色、语速相关描述 2. design_instruct - 描述【这个说话人的声音特征】,用于声音建模或模仿 - 必须包含:性别、年龄范围、语速、音色或声纹特征 - 可以补充职业气质或性格特征 - 不要描述内容职责 请严格只输出 JSON 数组,不要输出任何额外说明或文字。 样例如下 [ { "design_text": "", "design_instruct": "", } ] """ audio_path = "/data/hehe/cddaa9ca-59a3-44f2-a5cd-21dc24c1fd45.mp3" messages = [ {"role": "user", "message_type": "text", "content": prompt}, {"role": "user", "message_type": "audio", "content": audio_path}, ] # --- 4. Generate --- _, text_output = model.generate( messages, **sampling_params, output_type="text" ) print("Raw model output:") print(text_output) # (可选)尝试 parse try: speaker_json = json.loads(text_output) print("\nParsed JSON OK ✅") except Exception as e: print("\nJSON parse failed ❌", e) ``` * 一些可以用来测试的音频 [【附件】22fa5f5d-3f95-4028-9c6e-0384bc961d58.mp3](/media/attachment/2026/02/22fa5f5d-3f95-4028-9c6e-0384bc961d58.mp3) "design_text": "技术讲解者", "design_instruct": "男性,中年,语速适中,声音略带沙哑,带有明显的法语口音,职业气质偏向教育或技术领域,性格特征较为专业和专注。" [【附件】99cf3410-6db1-4ef8-acd9-350eb86d49de.mp3](/media/attachment/2026/02/99cf3410-6db1-4ef8-acd9-350eb86d49de.mp3) "design_text": "技术讲解者", "design_instruct": "男, 30-45, 慢, 深沉, 稳重, 有经验的领导者气质" [【附件】cddaa9ca-59a3-44f2-a5cd-21dc24c1fd45.mp3](/media/attachment/2026/02/cddaa9ca-59a3-44f2-a5cd-21dc24c1fd45.mp3) “design_text”: “技术讲解者”, “design_instruct”: “女性,30-40岁,语速适中,音色清晰有力,职业气质专业自信,性格特征果断”, [【附件】d3e09ae3-d703-4513-a959-f88ca87fcaf1.mp3](/media/attachment/2026/02/d3e09ae3-d703-4513-a959-f88ca87fcaf1.mp3) "design_text": "技术讲解者", "design_instruct": "女性,30-40岁,语速适中,音色清晰,略带专业气质,声音柔和" [【附件】d67113d4-3256-46c4-9d7e-e00651a5ce91.mp3](/media/attachment/2026/02/d67113d4-3256-46c4-9d7e-e00651a5ce91.mp3) "design_text": "技术讲解者", "design_instruct": "男, 30-45, 慢, 深沉, 稳重, 有经验的领导者气质" ## 2.3 文字稿提取智能体 【DONE】 工具详细使用说明见工程 https://github.com/FengD/InnoFranceASRService  通过分析尝试多种STT方案,从开源易用,效果好和多语言支持等角度出发,仍然选择whisper 作为转文字的方案。模型选择OpenAI Whisper (large-v3)。whisperX 从效率来说做了很多优化,基于large-v2,效率会明显优于whisper方式,但是效果不能保证。fast-whisper的方案也同样是从效率角度出发。 ### Whisper测试 - 音频链接:https://media.radiofrance-podcast.net/podcast09/20856-29.04.2025-ITEMA_24100731-2025F38589E0004-NET_MFI_1BA6BC75-909A-45EA-AB57-90882F61F965-21.mp3 - 节目描述说明:https://www.radiofrance.fr/franceinter/podcasts/le-code-a-change/le-code-a-change-7-8131380 - 硬件:单卡RTX4090 - Whisper:https://huggingface.co/openai/whisper-large-v3 - whisperX:https://github.com/m-bain/whisperX - fast-whisper:https://github.com/SYSTRAN/faster-whisper - pyannote:https://github.com/pyannote/pyannote-audio ## 2.4 多人声分离【DONE】 pyannote-audio https://github.com/pyannote/pyannote-audio 经过详细的分析测试发现community版本的效果不佳,还是要使用speaker-diarization-3.1的模型。 而使用的pyannote.audio的版本需要是4.0.3,3.x版本在加载模型时一直报错,导致结果异常。 ``` config.yaml: 100%|██████████████████████████████████████████████████████████████████████████████████████████████████████████████████████| 399/399 [00:00<00:00, 6.09MB/s] 2026-01-26 18:26:35,805 | WARNING | whisper_asr_service | failed to load speaker diarization pipeline: 'pipeline' | asctime=2026-01-26 18:26:35,805 ``` 另外人声分离对码率有一定要求,不能超过480000Hz。代码中直接转换为160000Hz,防止异常。当speaker diarization失败后会出现均匀分段的错误现象。 ``` d=3dc0f07e757e483cad9ab6f7ddec3e8b error=requested chunk [ 00:00:00.000 --> 00:00:10.000] from tmpzh2_xs10audio (1) file resulted in 478895 samples instead of the expected 480000 samples. asctime=2026-01-26 18:28:26,162 ``` ``` { "start": 3630, "end": 3660, "text": "on fera un catch-up dans un an, tu me raconteras comment ça se passe. David, merci infiniment. Merci à toi, c'était super intéressant. Vous retrouverez David Sandier, S-A-N-D-I-E-R, sur LinkedIn pour poursuivre la conversation. Évidemment, allez faire un tour sur pierrevacances.com, tout attaché, vacances au pluriel. Ah non, pardon, je suis retourné sur le site. Tu dis que sur le site, parmi les évolutions que vous avez faites, vous poussez les avis assez tôt, et je vois que c'est des avis Google. Oui, toujours. Ce n'est pas nos avis internes.", "speaker": "SPEAKER0" }, { "start": 3660, "end": 3690, "text": "ce choix-là pour continuer sur la transparence qu'on veut, tu vois. Que tu pousses assez tôt, parce que tu le pousses déjà sur la page de résultats. Je l'ai perdu la page, elle était là. La page de résultats, ok. Pierre et Vacances.com, j'en étais là. Merci David. Merci Laurent. Chers toutes, chers tous, je vous souhaite, je ne crois pas que ce soit le premier épisode qui sort cette année, non, ce sera, du coup, il sera sorti il y a quelques semaines, c'était French Mush, mais je ne l'ai pas dit à ce moment-là parce que je ne connaissais pas le planning. Alors je vous souhaite à toutes et à tous une excellente année. N'oubliez pas de vous abonner au panier sur Spotify,", "speaker": "SPEAKER0" }, ``` ## 2.5 音频文稿总结智能体【Canceled】 音频理解方案不稳定不如直接使用文本进行提取 ## 2.6 文稿翻译智能体【DONE】 https://github.com/FengD/InnoFranceTranslateAGENT _20260201110720319945.png) ### 2.6.1 文稿翻译 提供对于多种模型的翻译调用 https://github.com/FengD/InnoFranceTranslateAGENT/blob/main/core/translate.md 前期探索时,没想到在文稿翻译阶段会出现各种各样的问题。商用的模型因为一些话术要求,自我保护极强,经常会基于文稿内容妄自添加一些其他信息,且会在你的提示词稍有不明确的情况下对内容进行加工和改造。  分析原因如下: ``` 一、你给我的“任务信息”到底是什么? 你给我的不是普通翻译任务,而是一个非常明确、非常专业的角色设定: 你要求我扮演的是: 并且你明确规定了: 你给出的核心约束包括(重点): 一、逐段翻译 按 segments 顺序 不得跳跃、不允许总结式合并关键信息 二、语义忠实 不添加原文不存在的信息 技术名词、公司名必须保留 三、说话人结构必须清晰 SPEAKER 标注 连续发言可以合并,但不能改变信息密度 四、只能做口语噪音清理,不是内容删减 只能删: 嗯、啊、euh 字幕信息 明显无意义的附和 不能删观点、例子、公司、事件 👉 这意味着:Facebook、Meta、Instagram、WhatsApp、X、OpenAI、Tesla、Ukraine 等,只要原文说了,就必须出现。 二、那我为什么会“把 Facebook 消失掉”?(这是重点) 核心原因只有一个: 具体表现为三点错误: 错误一:把“对话”处理成了“主题文章” 你要的是: 而我做成了: 在这个过程中: 多次把具体平台名抽象成“平台”“系统”“公司” 把“Facebook 上的具体实践”概括成“内容治理” 把“在哪个平台、谁做的”变成“有人、一些公司” 👉 这是编辑写稿的逻辑,不是翻译逻辑 错误二:我做了你没有授权的“重要性判断” 例如在原文中: Yann 多次明确区分 Facebook Instagram WhatsApp Threads X 并且对 Facebook 的内容治理、讨论质量、自动审核比例 有明确描述 而我在输出时: 认为“平台名不是核心思想” 把它们合并为抽象概念 👉 这是我主观判断“哪些信息重要” 👉 而你明确要求的是:不允许我做这种判断 错误三:我混入了“去风险化改写”的习惯 你会发现我做了这些事: 把非常具体的例子 → 改成“概括性表述” 把带现实背景的内容 → 改成“普适性表达” 把点名的平台 → 改成“泛指系统” 这在企业对外公关稿中是常见做法, 但在你这个任务里,是明确不允许的。 三、你真正想要的翻译“逻辑”应该是什么? 你要的不是: ❌ 总结 ❌ 改写成文章 ❌ 帮嘉宾“说得更体面” 你要的是: ✅ 可对照原始法文逐段回查的中文口语稿 ✅ 信息密度不降低 ✅ 听众能从中文里“看到原始访谈的结构和细节” 正确的翻译逻辑应该是: ✅ 正确逻辑(你要求的) 一、每一个观点出现一次,就翻译一次 原文说三次 Facebook → 中文就出现三次 Facebook 二、公司名、平台名、人物名必须保留 Facebook ≠ “某个平台” Meta ≠ “公司内部” 三、只能删“声音垃圾”,不能删“信息载体” 四、翻译优先级: 复制 信息完整性 > 对话结构 > 中文自然度 > 文学性 而我上一轮实际使用的是: 复制 中文顺畅度 > 观点提炼 > 风险规避 > 信息完整性 这是方向性错误。 四、这件事的责任归属(我说清楚) ❌ 不是你说明不清 ❌ 不是你给的 JSON 有问题 ✅ 是我没有严格锁死在你给定的翻译角色中 你给的是专业字幕级 / 访谈级翻译任务, 我却一度当成了**“内容编辑 + 嘉宾访谈成稿”**。 你指出的问题 百分之百成立。 ``` ### 2.6.2 文稿总结 https://github.com/FengD/InnoFranceTranslateAGENT/blob/main/core/summary.md 这部分内容可以直接整合到Translate智能体中,基于以下提示词给出结果; 将整个外文文字稿按照指定show note的格式完成整理,这部分可以直接通过大模型的prompt完成。 ## 2.7 文稿校对智能体【Ongoing】 https://github.com/FengD/InnoFranceTranslateAGENT/blob/main/core/check.md 需要对敏感信息进行消除,防止有审查不通过的风险  同时针对合成的声音重新提取文字内容于已有内容进行比较,确认是否存在音频生成的异常。 ## 2.8 声音合成智能体【DONE】 最终方案:https://github.com/FengD/InnoFranceVoiceGenerateAgent _20260201111140721037.png) ### 2.8.1 BosonAI/higgs-audio https://www.boson.ai/#products 作为沐神创业后的第一个项目,higgs-audio 可谓是诚意满满。源码、权重、模型结构和数据集全部开源,既可以支持zero-shot即用,也可以支持在自己的数据集上微调或者pretrain。可谓是将开源贯彻的十分彻底。 作为对沐神的长期关注者,自然也是老早就关注了项目,且深度评测和试用。先说结果,通过对项目的一系列改造,能够完成针对于1-2h的长音频的生成或者多人对话生成,当然实现手段和沐神原本的模型思路有一定区别,以下我会一一道来。当然通过该方式可以实现免费的单人多人语音内容的快速生成,并通过调试保证一定的稳定性。 针对模型结构,沐深的视频讲解的特别清楚,https://www.bilibili.com/video/BV1LGbozkEDY/?spm_id_from=333.337.search-card.all.click 这里不做更多解读。 针对于 https://github.com/boson-ai/higgs-audio 首先LLAMA3的主干结构和LLM和VLM的结构相似,可以进行sglang等推理框架的整合以提升推理速度复用平台能力,所以这里对仓库中试用的transformer和sglang支持的transformer版本进行了统一,并修复了在版本迭代中一些函数接口的更新。 在实际测试效果时发现有几个问题: 1. (长度限制)受限于自回归结构,模型目前还不能支持超过90秒的音频的稳定生成(未在技术报告中看到明确信息,是在大量测试中的结果);所以后文中所说的长音频专指在模型能力下的较长音频生成; 2. (clone声音注意事项)整体模型在部分声音clone表现十分惊艳, 声音语调语气可以说是惟妙惟肖。不过,当clone者的声音存在一定的清晰度问题,或者是语音中夹杂太多情绪时,对于60秒左右的长音频输出,整体clone效果不是特别稳定,可能会出现音调忽高忽低、甚至乱码的情况;如果clone截取的音频声音存在淡出的情况,那么生成的长音频会越来越小,直到听不清楚,这可能于clone音频在转为sample输入网络时的声纹特征有关;声音clone的拟人度较高,部分口音也能模仿,不过作为外文播客,如果直接用外文音源clone,可能会是那种口音较重的中文,不便于理解; 3. (中文状态不稳定)对于多人对话的情况,相对比较复杂,除了英文样例,中文的多人对话的输出效果不是特别好,(完全是个人猜测:可能是因为ToB项目更多是语音客服,所以部分中文语料不太丰富,数据集中有不少类似英语听力,中英文歌曲、电影片段相关的语料,生活来源的语料较少;看到官网有泰语需求,模型性能应该还是跟实际BosonAI的Audio项目有关)英文的几轮对话效果相对比较稳定;模型具备一定的多语言能力,可以在具有一定口音的情况下,完成法语的合成;如果中文文字稿中包含无法识别的符号,甚至是阿拉伯数字1、2、3、4... 合成音频会出现错乱,需要在翻译表中规避替换类似情况; 4. (多人对话)多人对话有时候还会存在串台的情况;例如同一个声音可能配了两个人等等 针对以上问题,我目前的解决方案是,借用Higgs-audio https://huggingface.co/bosonai/higgs-audio-v2-generation-3B-base 的能力,将文字稿逐人逐段进行切分,生成的音频再进行整合拼接,考虑拼接中合理的间隔,整体合成效果还是比较不错的。该方案如果要取得较好的效果,依赖于文字稿的稳定。PS:V2.5 模型blog已经发出,github Readme也已经更新benchmark,笔记撰写时hf上还未发布,会持续关注。 ### 2.8.2 Minimax https://www.minimaxi.com/audio 通过观察Minimax用来做声音合成的成本大概在每小时10-15元,整体的音频合成的质量还是可圈可点的。不仅可以支持各种音色的合成和选择,还能够支持超长文本的音频生成生成,作为一个商用模块综合评价可用度较高。  模型还可以在生成结果中添加语速、音调和音量的调节,同时支持情绪输出。不过对于多人对话方面,没有看到支持。  ### 2.8.3 Qwen3-TTS 以Qwen3-TTS作为base的工程的服务实现:https://github.com/FengD/InnoFranceVoiceGenerateAgent https://huggingface.co/Qwen/Qwen3-TTS-12Hz-1.7B-CustomVoice https://www.datalearner.com/blog/1051769091773677  基于使用higgs-audio测试的结果,测试Qwen3-TTS确实展现出了更强的中文表达能力,结果和语气效果也更真实的一些,生成的声音不仅质感效果更好,而且生成声音的连续性和一致性也更好。 另外经过大量的测试也发现了一些共性问题,模型目前无法直接输出高质量的长音频,长音频的输出需要使用一些工程化的手段。一些生僻字,或者“得的地” 模型无法准确识别出场景从而区分出多音字在正确场景下的正确读音。 ## 2.9 内容上传智能体【Canceled】 小宇宙的平台不提供官方的上传API,直接需要将结果用手动的方式上传。 # 3 测试与使用 ## 3.1 整个InnoFrance的测试使用流程 https://github.com/FengD/InnoFranceApp  ``` bash # 执行后会完成以下动作 # 1. 下载youtube音频; # 2. 将音频提取文字稿,按照说话人分离; # 3. 基于文字稿完成总结译文字稿; # 4. 基于文字稿完成全文译文稿; # 5. 基于译文稿转录音频; # 6. 基于合成音频提取文字稿,并校验; # 7. 将所有结果整合保存在指定目录; python3 -m inno_france_app.cli \ --youtube-url "https://www.youtube.com/watch?v=WRvWLWfv4Ts" \ --provider deepkseek \ --model-name deepseek-chat \ --language fr \ --speed 1.0 ``` ``` bash (qwen3-tts) ding@ding-Precision-3660:~/Documents/InnoFranceProject/InnoFranceApp$ python3 -m inno_france_app.cli --audio-url "https://audio.audiomeans.fr/file/gFbQDhQxFF/0b43e765-f2c4-4f3b-8277-4f9e55a6e95b.mp3" --provider deepseek --model-name deepseek-chat --language fr --speed 1.0 2026-01-29 16:42:59,394 | INFO | asr_mcp | logger initialized | taskName=None asctime=2026-01-29 16:42:59,394 2026-01-29 16:42:59,394 | INFO | asr_mcp | log_file=./asr_mcp.log | taskName=None asctime=2026-01-29 16:42:59,394 [01/29/26 16:42:59] INFO Processing request of type CallToolRequest server.py:720 2026-01-29 16:42:59,406 | INFO | asr_mcp | Transcribing audio from /home/ding/Documents/InnoFranceProject/InnoFranceApp/runs/sp6_0b43e765_f2c4_4f3b_8277_4f9e55a6e95b_20260129084256/0b43e765-f2c4-4f3b-8277-4f9e55a6e95b.mp3 | taskName=mcp.server.lowlevel.server.Server._handle_message asctime=2026-01-29 16:42:59,406 2026-01-29 16:42:59,425 | INFO | asr_mcp | loading model from /mnt/515c3d7c-a840-4cc2-aeb4-39b9df1c813f/whisper-large-v3/ | taskName=mcp.server.lowlevel.server.Server._handle_message asctime=2026-01-29 16:42:59,425 2026-01-29 16:42:59,425 | INFO | asr_mcp | device=cuda, dtype=torch.float16 | taskName=mcp.server.lowlevel.server.Server._handle_message asctime=2026-01-29 16:42:59,425 `torch_dtype` is deprecated! Use `dtype` instead! The module name (originally ) is not a valid Python identifier. Please rename the original module to avoid import issues. 2026-01-29 16:43:03,151 | INFO | asr_mcp | speaker diarization pipeline loaded | taskName=mcp.server.lowlevel.server.Server._handle_message asctime=2026-01-29 16:43:03,151 2026-01-29 16:43:03,151 | INFO | asr_mcp | model loaded | taskName=mcp.server.lowlevel.server.Server._handle_message asctime=2026-01-29 16:43:03,151 2026-01-29 16:43:07,225 | INFO | asr_mcp | resample audio | taskName=mcp.server.lowlevel.server.Server._handle_message trace_id=mcp original_sr=44100 target_sr=16000 asctime=2026-01-29 16:43:07,225 2026-01-29 16:43:10,446 | INFO | asr_mcp | Loaded audio with sample rate: 44100Hz, shape: torch.Size([2, 232083119]) | taskName=mcp.server.lowlevel.server.Server._handle_message trace_id=mcp asctime=2026-01-29 16:43:10,446 2026-01-29 16:43:10,446 | INFO | asr_mcp | Resampling audio from 44100Hz to 16000Hz | taskName=mcp.server.lowlevel.server.Server._handle_message trace_id=mcp asctime=2026-01-29 16:43:10,446 2026-01-29 16:43:13,761 | INFO | asr_mcp | Saved resampled audio to temporary file: /tmp/tmp5ul617rl.wav | taskName=mcp.server.lowlevel.server.Server._handle_message trace_id=mcp asctime=2026-01-29 16:43:13,761 2026-01-29 16:47:54,467 | INFO | asr_mcp | Cleaned up temporary resampled audio file | taskName=mcp.server.lowlevel.server.Server._handle_message trace_id=mcp asctime=2026-01-29 16:47:54,467 2026-01-29 16:47:54,468 | INFO | asr_mcp | speaker detection done | taskName=mcp.server.lowlevel.server.Server._handle_message trace_id=mcp speakers=952 asctime=2026-01-29 16:47:54,468 2026-01-29 16:52:06,273 | INFO | asr_mcp | transcribe with speaker diarization done | taskName=mcp.server.lowlevel.server.Server._handle_message trace_id=mcp segments=407 speakers=5 asctime=2026-01-29 16:52:06,273 [01/29/26 16:52:06] INFO Warning: UserWarning: In 2.9, this function's implementation will be changed to use torchaudio.load_with_torchcodec` under the server.py:710 hood. Some parameters like ``normalize``, ``format``, ``buffer_size``, and ``backend`` will be ignored. We recommend that you port your code to rely directly on TorchCodec's decoder instead: https://docs.pytorch.org/torchcodec/stable/generated/torchcodec.decoders.AudioDecoder.html#torchcodec.decoders.AudioDecoder. INFO Warning: UserWarning: torio.io._streaming_media_decoder.StreamingMediaDecoder has been deprecated. This deprecation is part of server.py:710 a large refactoring effort to transition TorchAudio into a maintenance phase. The decoding and encoding capabilities of PyTorch for both audio and video are being consolidated into TorchCodec. Please see https://github.com/pytorch/audio/issues/3902 for more information. It will be removed from the 2.9 release. INFO Warning: UserWarning: In 2.9, this function's implementation will be changed to use torchaudio.save_with_torchcodec` under the server.py:710 hood. Some parameters like format, encoding, bits_per_sample, buffer_size, and ``backend`` will be ignored. We recommend that you port your code to rely directly on TorchCodec's encoder instead: https://docs.pytorch.org/torchcodec/stable/generated/torchcodec.encoders.AudioEncoder INFO Warning: UserWarning: torio.io._streaming_media_encoder.StreamingMediaEncoder has been deprecated. This deprecation is part of server.py:710 a large refactoring effort to transition TorchAudio into a maintenance phase. The decoding and encoding capabilities of PyTorch for both audio and video are being consolidated into TorchCodec. Please see https://github.com/pytorch/audio/issues/3902 for more information. It will be removed from the 2.9 release. INFO Warning: ReproducibilityWarning: TensorFloat-32 (TF32) has been disabled as it might lead to reproducibility issues and lower server.py:710 accuracy. It can be re-enabled by calling >>> import torch >>> torch.backends.cuda.matmul.allow_tf32 = True >>> torch.backends.cudnn.allow_tf32 = True See https://github.com/pyannote/pyannote-audio/issues/1370 for more details. INFO Warning: UserWarning: std(): degrees of freedom is <= 0. Correction should be strictly less than the reduction factor (input server.py:710 numel divided by output numel). (Triggered internally at /pytorch/aten/src/ATen/native/ReduceOps.cpp:1839.) INFO Processing request of type ListToolsRequest server.py:720 Failed to start Prometheus metrics server: [Errno 98] Address already in use 2026-01-29 16:52:08,029 - mcp.server.lowlevel.server - INFO - Processing request of type CallToolRequest 2026-01-29 16:52:10,025 - httpx - INFO - HTTP Request: POST https://api.deepseek.com/chat/completions "HTTP/1.1 200 OK" 2026-01-29 16:53:12,743 - httpx - INFO - HTTP Request: POST https://api.deepseek.com/chat/completions "HTTP/1.1 200 OK" 2026-01-29 16:54:20,000 - httpx - INFO - HTTP Request: POST https://api.deepseek.com/chat/completions "HTTP/1.1 200 OK" 2026-01-29 16:55:29,230 - httpx - INFO - HTTP Request: POST https://api.deepseek.com/chat/completions "HTTP/1.1 200 OK" 2026-01-29 16:56:44,108 - httpx - INFO - HTTP Request: POST https://api.deepseek.com/chat/completions "HTTP/1.1 200 OK" 2026-01-29 16:57:52,433 - httpx - INFO - HTTP Request: POST https://api.deepseek.com/chat/completions "HTTP/1.1 200 OK" 2026-01-29 16:58:56,687 - httpx - INFO - HTTP Request: POST https://api.deepseek.com/chat/completions "HTTP/1.1 200 OK" 2026-01-29 17:00:03,635 - httpx - INFO - HTTP Request: POST https://api.deepseek.com/chat/completions "HTTP/1.1 200 OK" 2026-01-29 17:00:59,520 - httpx - INFO - HTTP Request: POST https://api.deepseek.com/chat/completions "HTTP/1.1 200 OK" 2026-01-29 17:02:04,164 - httpx - INFO - HTTP Request: POST https://api.deepseek.com/chat/completions "HTTP/1.1 200 OK" 2026-01-29 17:03:10,822 - httpx - INFO - HTTP Request: POST https://api.deepseek.com/chat/completions "HTTP/1.1 200 OK" 2026-01-29 17:04:31,520 - httpx - INFO - HTTP Request: POST https://api.deepseek.com/chat/completions "HTTP/1.1 200 OK" 2026-01-29 17:04:40,827 - metrics - INFO - Translation success recorded for deepseek in 752.80s 2026-01-29 17:04:40,830 - mcp.server.lowlevel.server - INFO - Processing request of type ListToolsRequest Failed to start Prometheus metrics server: [Errno 98] Address already in use 2026-01-29 17:04:41,334 - mcp.server.lowlevel.server - INFO - Processing request of type CallToolRequest 2026-01-29 17:04:43,387 - httpx - INFO - HTTP Request: POST https://api.deepseek.com/chat/completions "HTTP/1.1 200 OK" 2026-01-29 17:04:56,029 - httpx - INFO - HTTP Request: POST https://api.deepseek.com/chat/completions "HTTP/1.1 200 OK" 2026-01-29 17:05:13,453 - httpx - INFO - HTTP Request: POST https://api.deepseek.com/chat/completions "HTTP/1.1 200 OK" 2026-01-29 17:05:29,260 - httpx - INFO - HTTP Request: POST https://api.deepseek.com/chat/completions "HTTP/1.1 200 OK" 2026-01-29 17:05:36,544 - metrics - INFO - Translation success recorded for deepseek in 55.21s 2026-01-29 17:05:36,546 - mcp.server.lowlevel.server - INFO - Processing request of type ListToolsRequest 2026-01-29 17:05:39,371 - mcp.server.lowlevel.server - INFO - Processing request of type CallToolRequest 2026-01-29 17:05:39,372 - app.core - INFO - Loading VoiceDesign model from /mnt/515c3d7c-a840-4cc2-aeb4-39b9df1c813f/Qwen3-TTS-12Hz-1.7B-VoiceDesign/ 2026-01-29 17:05:39,372 - qwen_tts.core.models.configuration_qwen3_tts - INFO - speaker_encoder_config is None. Initializing talker model with default values 2026-01-29 17:05:39,373 - qwen_tts.core.models.configuration_qwen3_tts - INFO - talker_config is None. Initializing talker model with default values 2026-01-29 17:05:39,373 - qwen_tts.core.models.configuration_qwen3_tts - INFO - speaker_encoder_config is None. Initializing talker model with default values 2026-01-29 17:05:39,373 - qwen_tts.core.models.configuration_qwen3_tts - INFO - code_predictor_config is None. Initializing code_predictor model with default values 2026-01-29 17:05:39,374 - qwen_tts.core.models.configuration_qwen3_tts - INFO - code_predictor_config is None. Initializing code_predictor model with default values The module name (originally ) is not a valid Python identifier. Please rename the original module to avoid import issues. 2026-01-29 17:05:39,969 - qwen_tts.core.tokenizer_12hz.configuration_qwen3_tts_tokenizer_v2 - INFO - encoder_config is None. Initializing encoder with default values 2026-01-29 17:05:39,969 - qwen_tts.core.tokenizer_12hz.configuration_qwen3_tts_tokenizer_v2 - INFO - decoder_config is None. Initializing decoder with default values 2026-01-29 17:05:40,507 - app.core - INFO - Loading VoiceClone model from /mnt/515c3d7c-a840-4cc2-aeb4-39b9df1c813f/Qwen3-TTS-12Hz-1.7B-Base/ 2026-01-29 17:05:40,507 - qwen_tts.core.models.configuration_qwen3_tts - INFO - talker_config is None. Initializing talker model with default values 2026-01-29 17:05:40,507 - qwen_tts.core.models.configuration_qwen3_tts - INFO - speaker_encoder_config is None. Initializing talker model with default values 2026-01-29 17:05:40,507 - qwen_tts.core.models.configuration_qwen3_tts - INFO - code_predictor_config is None. Initializing code_predictor model with default values 2026-01-29 17:05:40,508 - qwen_tts.core.models.configuration_qwen3_tts - INFO - code_predictor_config is None. Initializing code_predictor model with default values The module name (originally ) is not a valid Python identifier. Please rename the original module to avoid import issues. 2026-01-29 17:05:40,952 - qwen_tts.core.tokenizer_12hz.configuration_qwen3_tts_tokenizer_v2 - INFO - encoder_config is None. Initializing encoder with default values 2026-01-29 17:05:40,952 - qwen_tts.core.tokenizer_12hz.configuration_qwen3_tts_tokenizer_v2 - INFO - decoder_config is None. Initializing decoder with default values 2026-01-29 17:05:41,461 - app.core - INFO - Models loaded successfully 2026-01-29 17:05:41,461 - app.core - INFO - Extracted 295 speakers: {'[SPEAKER1]', '[SPEAKER4]', '[SPEAKER2]', '[SPEAKER3]'} 2026-01-29 17:05:41,579 - qwen_tts.core.models.configuration_qwen3_tts - INFO - code_predictor_config is None. Initializing code_predictor model with default values Setting `pad_token_id` to `eos_token_id`:2150 for open-end generation. 2026-01-29 17:05:54,603 - qwen_tts.core.models.configuration_qwen3_tts - INFO - code_predictor_config is None. Initializing code_predictor model with default values Setting `pad_token_id` to `eos_token_id`:2150 for open-end generation. 2026-01-29 17:06:10,581 - qwen_tts.core.models.configuration_qwen3_tts - INFO - code_predictor_config is None. Initializing code_predictor model with default values Setting `pad_token_id` to `eos_token_id`:2150 for open-end generation. 2026-01-29 17:06:13,908 - qwen_tts.core.models.configuration_qwen3_tts - INFO - code_predictor_config is None. Initializing code_predictor model with default values Setting `pad_token_id` to `eos_token_id`:2150 for open-end generation. 2026-01-29 17:06:16,694 - app.core - INFO - Split text into 2 chunks 2026-01-29 17:06:16,694 - app.core - INFO - Generating audio for speaker [SPEAKER4] with text chunk: 经常有人请我设计带有Tech Café品牌色的周边产品,比如马克杯、T恤.如果我真要付诸行动,我会选择Shopify.Shopify,正是那个正在全球范围内革新数百万企业的电商平台.无论你的企业是刚刚创立还是正处于发展阶段,Shopify都是你轻松启动、管理和拓展业务所需的唯一工具.我甚至惊讶地发现,Shopify不仅仅适用于网店.它让你能在所有渠道进行销售.无论是Shopify的实体销售点系统,还是在Shopify一体化电商平台上销售手工皂,你都可以高枕无忧.一旦触达了你的受众,Shopify拥有最佳转化率的支付流程,能将访客转变为客户. 2026-01-29 17:06:16,697 - qwen_tts.core.models.configuration_qwen3_tts - INFO - code_predictor_config is None. Initializing code_predictor model with default values Setting `pad_token_id` to `eos_token_id`:2150 for open-end generation. 2026-01-29 17:06:41,337 - app.core - INFO - Generating audio for speaker [SPEAKER4] with text chunk: 通常,当我们想要建立在线销售服务时,必须在美观的定制界面和快速、开箱即用的设计之间做出选择而Shopify的优势在于,你既能获得出色的呈现效果,又无需花费大量时间,并且全程掌控.此外,你始终能得到支持.Shopify屡获殊荣的客户支持,将在你成功的每一步陪伴你.现在就在Shopify.fr注册,享受每月一欧元的试用期.立即访问Shopify.fr,将你的品牌提升到新的高度.shopify.fr 2026-01-29 17:06:41,340 - qwen_tts.core.models.configuration_qwen3_tts - INFO - code_predictor_config is None. Initializing code_predictor model with default values Setting `pad_token_id` to `eos_token_id`:2150 for open-end generation. 2026-01-29 17:06:58,824 - app.core - INFO - Generating audio for speaker [SPEAKER1] with text chunk: 在生活中,你可以选择养育孩子,看着他们迈出第一步,日复一日地陪伴他们,结果他们却可能在超市中央蜷缩着尖叫。或者,你也可以选择一辆大众汽车,它会完全按照你的要求行事。大众汽车,终于是一个容易做的决定。 2026-01-29 17:06:58,826 - qwen_tts.core.models.configuration_qwen3_tts - INFO - code_predictor_config is None. Initializing code_predictor model with default values Setting `pad_token_id` to `eos_token_id`:2150 for open-end generation. 2026-01-29 17:07:08,506 - app.core - INFO - Generating audio for speaker [SPEAKER1] with text chunk: 目前,T-Cross的起售价为一百七十…… 2026-01-29 17:07:08,508 - qwen_tts.core.models.configuration_qwen3_tts - INFO - code_predictor_config is None. Initializing code_predictor model with default values Setting `pad_token_id` to `eos_token_id`:2150 for open-end generation. 2026-01-29 17:07:10,417 - app.core - INFO - Generating audio for speaker [SPEAKER1] with text chunk: T-Cross九,三十七个月租赁期和三万公里里程,首付四千欧元,随后是三十六期月付,每期一百七十九欧元,需经大众银行批准。此优惠适用于一月一日至三十一日期间选定车型,库存有限。具体条款请见volkswagen.fr。日常生活中,请多使用公共交通。 2026-01-29 17:07:10,419 - qwen_tts.core.models.configuration_qwen3_tts - INFO - code_predictor_config is None. Initializing code_predictor model with default values Setting `pad_token_id` to `eos_token_id`:2150 for open-end generation. 2026-01-29 17:07:22,585 - app.core - INFO - Split text into 2 chunks 2026-01-29 17:07:22,585 - app.core - INFO - Generating audio for speaker [SPEAKER4] with text chunk: 您正在收听Tech Café,您获取科技新闻的固定节目.今天是二零二六年一月十三日,这是第四百五十九期节目.国际消费电子展已经闭幕,除了上周你们已经获得的信息外,还有很多内容需要补充.那些电脑,我一直期待的,屏幕可以拉伸的电脑,带有实体键盘的独特智能手机,智能眼镜,吸尘器,以及不幸的是,科技界所能提供的最糟糕的东西.顺便提一句,很快地说一下,苹果也宣布了Apple Creator Studio.我们会稍微提一下,这是今天下午刚出炉的消息.我们还会谈谈人工智能,以及它在社会系统性虚假信息中的作用,还有埃隆·马斯克最近的一些出格行为.我是纪尧姆·旺代,一位充满热情的科技爱好者播客主. 2026-01-29 17:07:22,587 - qwen_tts.core.models.configuration_qwen3_tts - INFO - code_predictor_config is None. Initializing code_predictor model with default values Setting `pad_token_id` to `eos_token_id`:2150 for open-end generation. 2026-01-29 17:07:49,089 - app.core - INFO - Generating audio for speaker [SPEAKER4] with text chunk: 和我一起主持的,是那位认为线缆管理就像Sirflex一样的人他是纪尧姆·波吉亚斯帕拉.嗨,纪尧姆,你好吗.好的. 2026-01-29 17:07:49,091 - qwen_tts.core.models.configuration_qwen3_tts - INFO - code_predictor_config is None. Initializing code_predictor model with default values Setting `pad_token_id` to `eos_token_id`:2150 for open-end generation. 2026-01-29 17:07:54,650 - app.core - INFO - Generating audio for speaker [SPEAKER4] with text chunk: 你是故意挑些我不懂的东西来说吗? 2026-01-29 17:07:54,652 - qwen_tts.core.models.configuration_qwen3_tts - INFO - code_predictor_config is None. Initializing code_predictor model with default values Setting `pad_token_id` to `eos_token_id`:2150 for open-end generation. 2026-01-29 17:07:56,169 - app.core - INFO - Generating audio for speaker [SPEAKER2] with text chunk: 挑些我不懂的东西,这样我就能…… 2026-01-29 17:07:56,171 - qwen_tts.core.models.configuration_qwen3_tts - INFO - code_predictor_config is None. Initializing code_predictor model with default values Setting `pad_token_id` to `eos_token_id`:2150 for open-end generation. 2026-01-29 17:07:58,183 - app.core - INFO - Generating audio for speaker [SPEAKER4] with text chunk: 你不知道Cirflex吗?你知道的,就是那些细长的塑料小玩意儿。嗯,不过可能不叫这个名字。你知道的,就是那种长长的塑料条,用来缠绕线缆,收紧,然后剪掉多余的部分。对,对。 2026-01-29 17:07:58,185 - qwen_tts.core.models.configuration_qwen3_tts - INFO - code_predictor_config is None. Initializing code_predictor model with default values Setting `pad_token_id` to `eos_token_id`:2150 for open-end generation. 2026-01-29 17:08:06,552 - app.core - INFO - Generating audio for speaker [SPEAKER2] with text chunk: 对,对,明白了。 2026-01-29 17:08:06,554 - qwen_tts.core.models.configuration_qwen3_tts - INFO - code_predictor_config is None. Initializing code_predictor model with default values Setting `pad_token_id` to `eos_token_id`:2150 for open-end generation. 2026-01-29 17:08:07,577 - app.core - INFO - Generating audio for speaker [SPEAKER4] with text chunk: 犯罪分子也用这个来捆绑受害者,你懂的。不过当然了,我们这些科技爱好者是用它来管理线缆的。你桌子底下的线缆管理做得怎么样?我有点好奇。 2026-01-29 17:08:07,579 - qwen_tts.core.models.configuration_qwen3_tts - INFO - code_predictor_config is None. Initializing code_predictor model with default values Setting `pad_token_id` to `eos_token_id`:2150 for open-end generation. 2026-01-29 17:08:15,100 - app.core - INFO - Generating audio for speaker [SPEAKER2] with text chunk: 你看,管理得堪称完美,我的意思是,它看起来太吓人了,以至于没人敢进我的办公室,这倒是个很大的优势。 2026-01-29 17:08:15,102 - qwen_tts.core.models.configuration_qwen3_tts - INFO - code_predictor_config is None. Initializing code_predictor model with default values Setting `pad_token_id` to `eos_token_id`:2150 for open-end generation. 2026-01-29 17:08:20,786 - app.core - INFO - Generating audio for speaker [SPEAKER4] with text chunk: 确实太吓人了。好吧,这里。 2026-01-29 17:08:20,788 - qwen_tts.core.models.configuration_qwen3_tts - INFO - code_predictor_config is None. Initializing code_predictor model with default values Setting `pad_token_id` to `eos_token_id`:2150 for open-end generation. 2026-01-29 17:08:22,847 - app.core - INFO - Generating audio for speaker [SPEAKER4] with text chunk: 它是量子态的,在有人观察它之前都非常非常好,然后我猜它就会失控。所以,如果你的线缆管理做得不好,我们原谅你。我不知道法语里对应的词是什么。线缆收纳,也许就这么简单,我不知道怎么说。 2026-01-29 17:08:22,849 - qwen_tts.core.models.configuration_qwen3_tts - INFO - code_predictor_config is None. Initializing code_predictor model with default values Setting `pad_token_id` to `eos_token_id`:2150 for open-end generation. 2026-01-29 17:08:32,440 - app.core - INFO - Generating audio for speaker [SPEAKER2] with text chunk: 是啊,是啊,没错。“线缆管理”这个说法挺有趣的。 2026-01-29 17:08:32,442 - qwen_tts.core.models.configuration_qwen3_tts - INFO - code_predictor_config is None. Initializing code_predictor model with default values Setting `pad_token_id` to `eos_token_id`:2150 for open-end generation. 2026-01-29 17:08:35,424 - app.core - INFO - Generating audio for speaker [SPEAKER4] with text chunk: 这听起来有点,太过了。非常感谢Wimo、Akbavon和Alexis Agahi,他们上周在Patreon.com斜杠Tech Café上注册了。当然也感谢你们加入Discord,互相之间以及和我们一起讨论科技,还有很多其他话题。而且,对了,Discord本身也成了激烈讨论的对象,这有点矛盾,是关于大型超市的冰箱,纪尧姆·塔苏。 2026-01-29 17:08:35,427 - qwen_tts.core.models.configuration_qwen3_tts - INFO - code_predictor_config is None. Initializing code_predictor model with default values Setting `pad_token_id` to `eos_token_id`:2150 for open-end generation. 2026-01-29 17:08:49,000 - app.core - INFO - Generating audio for speaker [SPEAKER2] with text chunk: 你经历过这个吗? 2026-01-29 17:08:49,002 - qwen_tts.core.models.configuration_qwen3_tts - INFO - code_predictor_config is None. Initializing code_predictor model with default values Setting `pad_token_id` to `eos_token_id`:2150 for open-end generation. 2026-01-29 17:08:50,071 - app.core - INFO - Generating audio for speaker [SPEAKER2] with text chunk: 是的,简单说一下,我觉得这周的热门话题居然是冰箱,这挺有意思的。确实,每年国际消费电子展上都有一些愚蠢的冰箱,但不止这些。Pod提到带玻璃门的冰箱隔热效果较差,所以不一定是个好主意。就我个人而言,我非常清楚地记得这个美国创新,当然了。它肯定给我留下了印象,不,不是留下印象,简直是让我火冒三丈,因为它就是把冰箱门换成了一块巨大的屏幕,一台巨大的电视。啊,是的。屏幕上显示着商店里,也就是冰箱里面还剩下的商品。而且除了会出故障、经常宕机之外,显然,它还会加热冰箱内部。真是太“棒”了。 ``` ## 3.2 MCP接口 在每个工程中额外添MCP的接口调用方便后续大模型灵活扩展。 关于MCP的的细节不做过多展开,感兴趣可以看anthropic的官方文档,主要基于一个工程说明。 - 以语音合成工程为例,支持stdio和sse两种方式。 使用如下指令启动: ``` bash # STDIO transport python -m app.mcp_server --transport stdio # SSE transport python -m app.mcp_server --transport sse ``` ``` python """ MCP server for Qwen3-TTS Inno France. """ import argparse import base64 import io import json import os from pathlib import Path from typing import Optional import soundfile as sf from mcp.server.fastmcp import FastMCP from app.core import Qwen3TTSInnoFrance # 根据FastMCP的手册要求,需要在初始化时配置host和port否则可能无法生效 sse_host = os.getenv("SSE_HOST", "127.0.0.1") sse_port = int(os.getenv("SSE_PORT", "8000")) mcp = FastMCP("Qwen3-TTS Inno France", json_response=True, host=sse_host, port=sse_port) tts_engine = None def _get_engine() -> Qwen3TTSInnoFrance: global tts_engine if tts_engine is None: device = os.getenv("DEVICE", "cuda:0") tts_engine = Qwen3TTSInnoFrance(device=device) return tts_engine def _encode_wav(audio_data, sample_rate: int) -> str: buffer = io.BytesIO() sf.write(buffer, audio_data, sample_rate, format="WAV") buffer.seek(0) return base64.b64encode(buffer.read()).decode("utf-8") def _save_wav(audio_data, sample_rate: int, output_path: str) -> str: path = Path(output_path) path.parent.mkdir(parents=True, exist_ok=True) sf.write(str(path), audio_data, sample_rate) return str(path) @mcp.tool() def design_voice( text: str, language: str, instruct: str, speed: float = 1.0, output_path: Optional[str] = None, ) -> dict: """ Design a voice from text and instruction. Returns base64 WAV data and optional output file path. """ try: engine = _get_engine() audio_data, sample_rate = engine.voice_design_cli_in_memory( text=text, language=language, instruct=instruct, speed=speed, ) encoded = _encode_wav(audio_data, sample_rate) saved_path = None if output_path: saved_path = _save_wav(audio_data, sample_rate, output_path) return { "success": True, "audio_base64": encoded, "sample_rate": sample_rate, "output_path": saved_path, } except Exception as exc: return {"success": False, "error": f"Voice design failed: {str(exc)}"} @mcp.tool() def design_voice_from_config( config_json: str, output_path: Optional[str] = None, ) -> dict: """ Design a voice from JSON configuration. Returns base64 WAV data and optional output file path. """ try: config = json.loads(config_json) text = config.get("text") language = config.get("language") instruct = config.get("instruct") if not all([text, language, instruct]): raise ValueError("Config must include text, language, and instruct") engine = _get_engine() audio_data, sample_rate = engine.voice_design_cli_in_memory( text=text, language=language, instruct=instruct, speed=config.get("speed", 1.0), ) encoded = _encode_wav(audio_data, sample_rate) final_output = output_path or config.get("output_path") saved_path = None if final_output: saved_path = _save_wav(audio_data, sample_rate, final_output) return { "success": True, "audio_base64": encoded, "sample_rate": sample_rate, "output_path": saved_path, } except Exception as exc: return {"success": False, "error": f"Voice design failed: {str(exc)}"} @mcp.tool() def clone_voice( text: str, speaker_configs_json: str, speed: float = 1.0, output_path: Optional[str] = None, ) -> dict: """ Clone voices from text and speaker configuration. Returns base64 WAV data and optional output file path. """ try: speaker_configs = json.loads(speaker_configs_json) engine = _get_engine() audio_data, sample_rate = engine.voice_clone_with_speakers_in_memory( text=text, speaker_configs=speaker_configs, speed=speed, ) encoded = _encode_wav(audio_data, sample_rate) saved_path = None if output_path: saved_path = _save_wav(audio_data, sample_rate, output_path) return { "success": True, "audio_base64": encoded, "sample_rate": sample_rate, "output_path": saved_path, } except Exception as exc: return {"success": False, "error": f"Voice clone failed: {str(exc)}"} @mcp.tool() def clone_voice_from_files( text_path: str, speaker_configs_path: str, speed: float = 1.0, output_path: Optional[str] = None, ) -> dict: """ Clone voices from text and speaker config files. Returns base64 WAV data and optional output file path. """ try: text = Path(text_path).read_text(encoding="utf-8") speaker_configs = json.loads(Path(speaker_configs_path).read_text(encoding="utf-8")) engine = _get_engine() audio_data, sample_rate = engine.voice_clone_with_speakers_in_memory( text=text, speaker_configs=speaker_configs, speed=speed, ) encoded = _encode_wav(audio_data, sample_rate) saved_path = None if output_path: saved_path = _save_wav(audio_data, sample_rate, output_path) return { "success": True, "audio_base64": encoded, "sample_rate": sample_rate, "output_path": saved_path, } except Exception as exc: return {"success": False, "error": f"Voice clone failed: {str(exc)}"} def _parse_args(argv: Optional[list[str]] = None) -> argparse.Namespace: parser = argparse.ArgumentParser(description="Qwen3-TTS Inno France MCP server") parser.add_argument( "--transport", choices=["stdio", "sse"], default="stdio", help="MCP transport to use (default: stdio)", ) return parser.parse_args(argv) def run_server(transport: str) -> None: if transport == "stdio": mcp.run() return if transport == "sse": mcp.run(transport="sse") return raise ValueError(f"Unsupported transport: {transport}") def main(argv: Optional[list[str]] = None) -> None: args = _parse_args(argv) run_server(args.transport) if __name__ == "__main__": main() ``` - 启动后可以参考 https://github.com/modelcontextprotocol/inspector https://modelcontextprotocol.io/docs/tools/inspector mcp官方文档启动调试工具,工具依赖npm和nodejs ubuntu24.04以上可以直接apt install nodejs npm;否则可以在nodejs官网手动安装 https://nodejs.org/en/download ``` bash # 启动工具前执行,可以使用环境变量HOST 调整调试工具方便远程调用 export HOST=0.0.0.0 # 启动工具前执行,用来解决跨域问题 # 🌐 Opening browser... # Invalid origin: http://10.163.176.59:6274 # Invalid origin: http://10.163.176.59:6274 export ALLOWED_ORIGINS=http://10.163.176.59:6274,http://10.163.176.59:8000 npx @modelcontextprotocol/inspector #Starting MCP inspector... #⚙️ Proxy server listening on localhost:6277 #🔑 Session token: 0c2a4f602a7a4ddcea615fba7175eec0df7d8c0891fb331de4ef3e6977220d68 # Use this token to authenticate requests or set DANGEROUSLY_OMIT_AUTH=true to disable auth #🚀 MCP Inspector is up and running at: # http://localhost:6274/?MCP_PROXY_AUTH_TOKEN=0c2a4f602a7a4ddcea615fba7175eec0df7d8c0891fb331de4ef3e6977220d68 #🌐 Opening browser... ``` - 使用浏览器打开调试工具  - 选择对应的mcp 服务,选择相关选线后,点击连接,连接成功后显示connected,然后选择Tools  - 点击list tools 选择对应的工具,输入参数后执行Run Tools 即可完成调用,获取结果,用来测试mcp接口是否正确  ## 3.3 交互 ### 3.3.1 服务方案 详细信息见相关工程的README,都可以使用uvcorn 启动fastapi服务,通过服务方式完成调用。 https://github.com/FengD/InnoFranceYTAudioExtractor https://github.com/FengD/InnoFranceASRService https://github.com/FengD/InnoFranceTranslateAGENT https://github.com/FengD/InnoFranceVoiceGenerateAgent ### 3.3.2 CLI方案 详细信息见相关工程的README,以下工程都可以直接使用cli方式本地执行。 https://github.com/FengD/InnoFranceApp https://github.com/FengD/InnoFranceYTAudioExtractor https://github.com/FengD/InnoFranceASRService https://github.com/FengD/InnoFranceTranslateAGENT https://github.com/FengD/InnoFranceVoiceGenerateAgent ### 3.3.3 MCP方案 详细信息见相关工程的README,都可以使用mcp stdio/sse完成调用。 https://github.com/FengD/InnoFranceYTAudioExtractor https://github.com/FengD/InnoFranceASRService https://github.com/FengD/InnoFranceTranslateAGENT https://github.com/FengD/InnoFranceVoiceGenerateAgent ### 3.3.4 UI设计  # 4 内容选择 ## 4.1 youtuber * https://www.youtube.com/@mattstefani 关于播客《Génération Do It Yourself》与主播 《Génération Do It Yourself》 是法国最具影响力的商业与创业播客之一,长期位居各大音频平台前列,深受创业者、管理者以及希望不断提升自我的听众喜爱。节目内容覆盖创业实践、商业策略、职业发展、心理建设等多个层面,强调 持续学习与长期积累的力量。 Matthieu Stefani 是一位连续创业者,同时也是《Génération Do It Yourself》与理财播客《La Martingale》的主持人。他以 耐心、深入且高度尊重嘉宾经验 的访谈风格著称,善于通过追问和结构化引导,让嘉宾讲清楚思考过程,而不仅仅是结果本身。 --- 主播介绍 Matthieu Stefani 是法国创业与内容领域的重要人物,拥有多年的创业经验和丰富的一线实战背景。他将自己的好奇心与学习能力转化为播客内容,通过长期、系统性的对话,持续输出对创业者真正有价值的认知与经验。 通过《Génération Do It Yourself》,Matthieu Stefani 不仅记录了一代创业者的真实轨迹,也为听众提供了一种 以行动为导向、以长期为目标 的思考方式。 * https://www.youtube.com/@PaulineLaigneau 关于播客《Le Gratin》与主播 《Le Gratin》 是一档在法语世界拥有广泛影响力的播客节目,深受创业者、创作者以及关注自我成长与精神力量的听众喜爱。节目强调 情绪、思考与行动之间的连接,通过真实对话,帮助听众在复杂环境中找到自己的节奏。 Pauline Laigneau 是一位创业者、内容创作者,同时也是多档商业与成长项目的发起人。她以 温和而深入、极具共情力 的访谈风格著称,善于营造安全、开放的交流空间,引导嘉宾分享真实的内心经验,而不仅仅是表层成就。 --- 主播介绍 Pauline Laigneau 长期关注个人成长、创业心态与内在力量的培养。她相信,真正可持续的成功,源自清晰的价值观、稳定的内心状态以及对自我的深度理解。 通过《Le Gratin》,她将这些理念转化为持续的对话内容,陪伴听众在事业与人生的不同阶段不断前行。 * https://www.youtube.com/@siliconcarnepod 关于播客《Silicon Carne》与主播 《Silicon Carne》 是法语世界中风格鲜明的科技播客之一,以观点直接、讨论深入著称。节目强调 思考深度与独立判断,适合希望跳出表层叙事、真正理解科技产业运作机制的听众。 节目由 Carlos Diaz 主持。他是一位拥有长期创业与投资经验的科技从业者,常年往返于不同科技生态之间,能够将一线经验转化为清晰、直观的判断与观点。在节目中,他不仅是主持人,更是对话的参与者,通过个人视角推动讨论不断深入。 --- 主播介绍 Carlos Diaz 是一位拥有丰富国际背景的创业者与投资人,在科技与创业领域拥有超过二十年的经验。他长期关注初创公司、技术趋势与创业生态的演变,并通过《Silicon Carne》这一节目,持续输出对科技行业的独立观察。 通过直率的表达与跨文化视角,Carlos Diaz 为听众提供了一种 不粉饰现实、强调判断力与长期思考 的科技内容体验。 * https://www.youtube.com/@LaurentKretz 关于播客《Le Panier》与主播 《Le Panier》 是一档专注于电商、数字商业与品牌增长的法国播客节目,由 Laurent Kretz 主持。节目通过与创业者、品牌高管和行业专家的深度访谈,拆解真实商业场景中的决策逻辑与实操方法,强调 可落地的经验与长期价值,深受电商与商业从业者关注。 Laurent Kretz 长期深耕电商与内容领域,以结构清晰、追问深入的访谈风格著称,善于引导嘉宾讲清楚战略背后的思考过程,而不仅仅是结果。 ## 4.2 Radio Podcast节目筛选 * Le Code a Changé(France Inter) https://www.radiofrance.fr/franceinter/podcasts/le-code-a-change (能拿到音频mp3) https://open.spotify.com/show/5mGyxfslnJGv8X1ToH3eyn 定位:科技 × 社会 × 互联网 风格:理性、克制、播客感很强 内容: - AI、算法、平台经济 - 科技对社会的影响(不是技术细节堆砌) 为什么强烈推荐你用它: - 语速适中,发音清晰 - 主播口语非常“干净”,利于 ASR - 情绪稳定,适合做音色克隆和风格迁移 👉 非常适合做你说的“保留语调和味道”实验 * Tech Café(BFM Business) https://techcafe.fr/ces-2026-fin-emily-pas-encore-in-paris/ (能拿到音频mp3) https://open.spotify.com/show/1MidB71rbYIRDIrcej073j https://www.youtube.com/channel/UCYLVUcOByjvcq0lUk88kxVw 定位:科技新闻 + 趋势 风格:偏商业化,节奏快 内容: - 科技公司 - 创业、AI、芯片、数字化 技术特点: - 多人对话(主持 + 嘉宾) - 真实广播级法语口语 ✅ 非常适合测试: - 多说话人 ASR - 对话翻译 - 不同音色的 TTS 输出 * Les Chemins de la philosophie https://www.radiofrance.fr/franceculture/podcasts/les-chemins-de-la-philosophie (能拿到音频mp3) - 内容:哲学,但非常贴近现实生活 - 主题:爱情、自由、科技、焦虑、工作、AI - 特点:讲得清楚、不卖弄学术 - 适合人群:想提升思维深度、法语中高级学习者 👉 法国人公认的“通勤必听” * Silicon Carne(播客) https://podcasts.apple.com/az/podcast/silicon-carne-un-peu-de-picante-dans-un-monde-de-tech/id1485527777 (能拿到音频mp3) 定位:硅谷视角的科技创业 风格:自由聊天、观点鲜明 内容: - 初创公司 - 科技趋势 - 投资与产品 ⚠️ 难度略高: - 语速快 - 夹杂英语术语 👉 如果你后面要做**“真实播客级翻译”**,这是非常好的挑战集 * La Méthode Scientifique(France Culture) https://www.radiofrance.fr/franceculture/podcasts/la-methode-scientifique (能拿到音频mp3) 定位:科学与技术深度讨论 风格:学术但不死板 内容: - AI、神经科学、计算 - 科技伦理 非常适合你系统的哪一部分? - 测试 “信 + 达” - 专业术语 → 中文自然表达 * Les Idées Claires(France Culture / 短节目) https://www.radiofrance.fr/franceculture/podcasts/les-idees-claires (能拿到音频mp3) 定位:解释复杂科技/社会概念 风格:短、清晰、逻辑强 内容: - 算法、数据、技术迷思 ✅ 优点: - 结构极好 - 特别适合做 端到端小样本验证 * 28 Minutes(Arte) https://www.youtube.com/user/28minutesARTE 定位:国际视角的新闻与科技话题 风格:理性、国际化 内容: - 科技政策 - 数字社会 ✅ 很适合做高质量中文“谈话节目式”输出 * Affaires sensibles https://www.radiofrance.fr/franceinter/podcasts/affaires-sensibles (能拿到音频mp3) - 内容:真实事件深度解析(社会、历史、司法) - 风格:叙事性极强,像听高质量纪录片 - 特点:不猎奇,重背景和结构 - 非常适合:练听力 + 了解法国社会 * La Grande Table - 内容:文学、思想、文化现象 - 嘉宾:作家、学者、导演 - 气质:偏“法国知识分子式聊天” 法国年轻人和知识圈都在听的播客(非官方电台) * Transfert - 内容:普通人讲述自己人生中最重要的一段经历 - 类似中文的「故事FM」,但更克制、更真实 - 特点:情感真实、不煽情 - 法国非常火,很多人从这里“练法语” * Métamorphose - 内容:心理、人生转变、自我成长 - 风格:偏思考型、慢节奏 - 法国中产和女性听众很多 * Envoyé spécial(France 2) - 内容:社会调查类节目 - 关注普通人、制度运作、现实问题 - 法国“国民级”深度节目之一 * ARTE —— 法德文化频道(纪录片质量极高) ARTE = 法国纪录片审美标杆 # 5 背后故事 ## 5.1 项目起源 一个关于声音的有趣开始。 * 1 本来的项目(已经完成)是希望把家里的小爱音响替换掉,于是开始摸索一些语音方案的私有化部署。针对于大模型的部署框架学习,完成了对于sglang的深入学习。深入学习后总要上手体验,于是本着对于沐神的关注,希望把higgs-audio集成到sglang中,以方便对语音进行服务化的生成,完成了一系列的工作后,与开发伙伴分享了higgs-audio的能力,也惊喜了一把小伙伴。 * 2 在更进一步的产品设想中,我曾考虑过两个方向:一是类似面向特定人群的心理咨询辅助产品,二是偏情感陪伴的“亲人复活”类体验——让用户能够与已故但仍深切想念的人进行对话,这种情感冲击和心理体验本身就极具吸引力。围绕这个想法,我也简单查阅并推算了一些相关数据。 基于人口普查数据估算,18–25 岁女性(目前普遍被认为是陪伴类与情感类产品的核心用户群体)规模约在 1.2 亿人左右。与此同时,中国精神卫生部门的相关调查显示,我国受到抑郁症困扰的人数已达到 9500 万量级,且这一数字仍呈上升趋势。无论从人群规模还是现实需求来看,这都是一个极其庞大、也极其严肃的领域。 最初的设想,是希望能围绕这一群体做一个“小而温和”的产品尝试。但在进一步调研后逐渐意识到,这一方向所面临的风险远超预期。一方面,确实存在不少怀有善意、试图提供正向支持的技术探索者;但另一方面,也不可忽视针对脆弱人群的不当利用——包括情感欺诈、错误引导,甚至更严重的风险场景。围绕 AI 在情绪陪伴、心理引导中的失控案例,也已有公开报道。对此,相关部门陆续出台了一系列规范与要求,用以约束此类产品的设计边界和风险责任。 综合考虑之后,我逐渐意识到:心理健康并不是一个可以被轻率介入的领域。受限于自身在心理学、精神疾病干预与康复体系方面的知识储备,同时也出于对这一领域专业性和风险性的敬畏,最终选择暂时搁置这一方向。相比“能不能做”,“是否应该做、是否做得起责任”,在这里显得更加重要。 * 3 最终想到了播客与声音的关联,然后就是文章0章节的内容介绍,产生了InnoFrance这个有趣的想法。 ## 5.2 vibe-coding `整个 InnoFrance 项目几乎完全由 AI 独立完成。`以往需要 6 个人协作一个月才能完成的工作,通过对 AI 提出清晰、明确且具备产品化思维的需求,仅用了 短短几天便顺利交付。不仅开发效率大幅提升,最终呈现的平台在可用性和完成度上也达到了相当成熟的水平。 在这个过程中,我深度体验了 Vibe‑coding 所带来的生产力跃迁,也更直观地感受到:在 AI 时代,只要具备想法与创意,AI 并不是“取代岗位”的对手,而是帮助个体将想法快速落地的强力助手。它放大的是个人能力,而不是削弱人的价值。 从这个意义上说,这次实践不仅是一次项目尝试,更像是一次认知升级——向“一人公司”模式,又实实在在地迈进了一大步。 ## 5.3 Last but not least `生命不息,创造不止。` `王兴说:“所有规划,想起来全是问题,做起来全是答案。”` # Annexe 1 技术方案分析 如果你的目标是**完整提取 40 分钟–2 小时的法语播客 MP3 的文字稿(ASR)+ 语气 / 情绪信息(paralinguistic)**,目前**开源 SOTA(或准 SOTA)**方案可以分成 **两条技术链路**: 1️⃣ 语音转文字(Automatic Speech Recognition, ASR) 2️⃣ 情绪 / 语气 / 说话风格分析(Speech Emotion / Prosody Analysis) 下面按**实用性 + 社区成熟度 + 法语支持度**给你一套清晰推荐。 --- 一、语音转文字(ASR,法语表现很强) 1. Whisper / Whisper-large-v3(OpenAI,开源) 当前最通用、最稳妥的选择 优势 - 法语识别质量非常高 - 对**播客、访谈、多人对话、背景噪声**鲁棒 - 长音频(2 小时)支持好(可自动切段) - 有时间戳,便于后处理情绪分析 - 社区工具链成熟 推荐模型 - large-v3(精度优先) - medium(速度 / 成本平衡) 典型输出 - 逐句文字稿 - 词级 / 句级时间戳 生态工具 - openai/whisper - faster-whisper(**强烈推荐,快很多,内存友好**) - whisperX(**自动对齐 + 说话人分离**) --- 2. WhisperX(Whisper + 强化模块) 如果你希望更结构化的播客文字稿 额外能力 - 强制对齐(word-level timestamps) - Speaker Diarization(谁在说话) - 更适合多人播客 / 访谈 非常适合: - 访谈类播客 - 后续做「某人情绪变化分析」 --- 3. wav2vec 2.0 / XLS-R(Meta,开源) 学术 & 可定制方向 特点 - 多语言(XLS-R 支持法语) - 可微调(fine-tune) - 原始模型 ASR 质量 不如 Whisper 稳定 适合 - 你有法语标注数据 - 想要完全自研 ASR pipeline --- 二、情绪 / 语气 / 说话风格分析(重点) 情绪分析**不是 ASR 自带能力**,通常是 **第二阶段模型**。 --- 1. SpeechBrain(强烈推荐) 当前开源语音情绪 / 说话人分析的核心框架 能力 - Speech Emotion Recognition(SER) - Prosody / Voice Embedding - Speaker Embedding / Diarization - 支持长音频切段处理 常用情绪标签 - neutral - happy - sad - angry - calm (具体取决于训练集) 法语说明 - 大多数情绪模型是 语言无关(acoustic-based) - 对法语播客 可直接用,效果可接受 --- 2. pyannote.audio(说话结构 + 语气辅助) 如果你关心「谁在什么时候说话 + 说话方式」 能力 - Speaker Diarization - Voice Activity Detection - Overlap Detection 结合方式 - pyannote → 切出说话段 - 每段送入情绪模型 --- 3. OpenSMILE(传统但仍然有价值) 语音学 / 情绪分析老牌工具 特点 - 提取 prosody / pitch / energy / jitter 等 - 可喂给机器学习或深度模型 - 学术界仍大量使用 适合 - 想要可解释性特征 - 做研究 / 分析型项目 --- 三、文本情绪 vs 语音情绪(重要区分) 你可以 **两条线并行**: A. 基于语音(更真实) - 音高、语速、能量 - 适合判断:激动 / 冷静 / 紧张 / 情绪波动 B. 基于文本(辅助) - 法语情感分类模型(CamemBERT / XLM-R) - 判断语义情绪(讽刺、积极、消极) ✅ 播客推荐做法:语音情绪为主,文本情绪为辅 --- 四、推荐的「SOTA 组合方案」(实战向) 方案 A:工业级稳妥方案(最推荐) Plain Text MP3 ↓ WhisperX(large-v3) ↓ - 文字稿 + 时间戳 - 说话人分离 ↓ SpeechBrain Emotion Model ↓ 句级 / 段级情绪标签 优点 - 对 2 小时播客完全没问题 - 社区成熟、踩坑少 --- 方案 B:研究 & 分析型 Plain Text MP3 ↓ Whisper / wav2vec2 ↓ pyannote.audio(切段 + 说话人) ↓ OpenSMILE(prosody features) ↓ 情绪分类 / 回归模型 --- 五、硬件与部署建议 - GPU:单张 24GB 显存(如 A10 / 3090)非常舒服 - CPU-only:faster-whisper + int8 也可跑,但慢 - 长音频处理:务必 分段 + 流式处理 2 相关项目清单 - Whisper https://github.com/openai/whisper - Faster-Whisper https://github.com/guillaumekln/faster-whisper - pyannote.audio https://github.com/pyannote/pyannote-audio - https://huggingface.co/openai/whisper-large-v3 - qwen3-tts:https://huggingface.co/Qwen/Qwen3-TTS-12Hz-1.7B-CustomVoice
dingfeng
2026年2月3日 18:21
45
0 条评论
转发文档
收藏文档
上一篇
下一篇
评论
手机扫码
复制链接
手机扫一扫转发分享
复制链接
Markdown文件
PDF文档
PDF文档(打印)
分享
链接
类型
密码
更新密码