diff --git a/CLAUDE.md b/CLAUDE.md deleted file mode 100644 index 621d810..0000000 --- a/CLAUDE.md +++ /dev/null @@ -1,138 +0,0 @@ -# CLAUDE.md - -This file provides guidance to Claude Code (claude.ai/code) when working with code in this repository. - -## 常用命令 - -### Python 后端播客生成器 - -* **生成播客**: - ```bash - python podcast_generator.py [可选参数] - ``` - 可选参数包括: - * `--api-key `: OpenAI API 密钥。 - * `--base-url `: OpenAI API 代理地址。 - * `--model `: 使用的 OpenAI 模型,默认为 `gpt-3.5-turbo`。 - * `--threads `: 生成音频的并行线程数,默认为 `1`。 - - **示例**: - ```bash - python podcast_generator.py --api-key sk-xxxxxx --model gpt-4o --threads 4 - ``` - -* **启动 FastAPI Web 服务**: - ```bash - python main.py - ``` - 默认在 `http://localhost:8000` 启动,提供 REST API 接口。 - -* **检查 TTS 语音列表**: - ```bash - python check/check_edgetts_voices.py - python check/check_indextts_voices.py - # 其他 TTS 服务检查脚本... - ``` - -### Next.js Web 应用 (web/ 目录) - -* **开发模式**: - ```bash - cd web - npm run dev - ``` - 在 `http://localhost:3000` 启动开发服务器。 - -* **构建生产版本**: - ```bash - cd web - npm run build - ``` - -* **启动生产服务器**: - ```bash - cd web - npm run start - ``` - -* **类型检查**: - ```bash - cd web - npm run type-check - ``` - -* **代码检查**: - ```bash - cd web - npm run lint - ``` - -* **安装依赖**: - ```bash - cd web - npm install - ``` - -## 高层代码架构 - -本项目是一个全栈播客生成器,包含 Python 后端和 Next.js Web 前端,核心功能是利用 AI 生成播客脚本并将其转换为音频。 - -### Python 后端架构 - -* **`podcast_generator.py`**: 主运行脚本,负责协调整个播客生成流程,包括: - * 读取配置文件 (`config/*.json`)。 - * 读取输入文件 (`input.txt`) 和 AI 提示词文件 (`prompt/*.txt`)。 - * 调用 OpenAI API 生成播客大纲和详细脚本。 - * 调用配置的 TTS 服务生成音频。 - * 使用 FFmpeg 合并生成的音频文件。 - * 支持命令行参数配置 OpenAI API 和线程数。 - -* **`main.py`**: FastAPI Web 服务,提供 REST API 接口: - * `/generate-podcast`: 启动播客生成任务 - * `/podcast-status`: 查询生成进度 - * `/download-podcast/`: 下载生成的音频文件 - * `/get-voices`: 获取可用的 TTS 语音列表 - -* **`tts_adapters.py`**: TTS 服务适配器,统一处理不同 TTS 服务的 API 调用。 - -* **`openai_cli.py`**: 负责与 OpenAI API 进行交互的模块。 - -* **`config/`**: 存放 TTS 服务和播客角色配置的 JSON 文件。例如 `edge-tts.json`。这些文件定义了 `podUsers` (播客角色)、`voices` (可用语音) 和 `apiUrl` (TTS 服务接口)。 - -* **`prompt/`**: 包含用于指导 AI 生成内容的提示词文件。 - * `prompt-overview.txt`: 用于生成播客整体大纲。 - * `prompt-podscript.txt`: 用于生成详细对话脚本,包含占位符 (`{{numSpeakers}}`, `{{turnPattern}}`)。 - -* **`check/`**: TTS 服务语音列表检查脚本,用于验证各种 TTS 服务的可用语音。 - -### Next.js Web 前端架构 (web/ 目录) - -* **技术栈**: Next.js 14 (App Router), TypeScript, Tailwind CSS, Framer Motion - -* **`src/app/`**: Next.js App Router 页面和 API 路由 - * `api/generate-podcast/route.ts`: 播客生成 API,与 Python 后端集成 - * `api/audio/[filename]/route.ts`: 音频文件服务 API - * `api/config/route.ts`: 配置管理 API - * `api/tts-voices/route.ts`: TTS 语音列表 API - -* **`src/components/`**: React 组件 - * `PodcastCreator.tsx`: 播客创建器主组件 - * `AudioPlayer.tsx`: 音频播放器组件 - * `ProgressModal.tsx`: 生成进度显示模态框 - * `ConfigSelector.tsx`: TTS 配置选择器 - * `VoicesModal.tsx`: 语音选择模态框 - -* **`src/types/`**: TypeScript 类型定义,定义了播客生成请求/响应的数据结构 - -* **集成方式**: Web 应用通过 Node.js 子进程启动 Python 脚本,实时监控生成进度,并提供音频文件访问服务。 - -### TTS 服务集成 - -项目设计为高度灵活,支持多种 TTS 服务: -* **本地服务**: Index-TTS, Edge-TTS -* **网络服务**: 豆包 (Doubao), Minimax, Fish Audio, Gemini TTS -* **配置方式**: 通过 `config/*.json` 中的 `apiUrl` 进行配置 - -### 音频处理 - -使用 FFmpeg 工具将各个角色的语音片段拼接成一个完整的播客音频文件。FFmpeg 必须安装并配置在系统环境变量中。 diff --git a/config/tts_providers.json b/config/tts_providers.json index 981c99c..87f3642 100644 --- a/config/tts_providers.json +++ b/config/tts_providers.json @@ -9,17 +9,17 @@ "api_url": null }, "doubao": { - "X-Api-App-Id": "null", - "X-Api-Access-Key": "null" + "X-Api-App-Id": null, + "X-Api-Access-Key": null }, "fish": { - "api_key": "null" + "api_key": null }, "minimax": { - "group_id": "null", - "api_key": "null" + "group_id": null, + "api_key": null }, "gemini": { - "api_key": "null" + "api_key": null } } \ No newline at end of file diff --git a/input.txt b/input.txt deleted file mode 100644 index bfd0d67..0000000 --- a/input.txt +++ /dev/null @@ -1,14 +0,0 @@ -```custom-begin -Start your podcast with “欢迎收听,来生小酒馆,客官不进来喝点吗?”,End with “感谢收听,欢迎下次再来” -```custom-end - -### AI产品与功能更新 - -1. B站最近推出了一项堪称"黑科技”的**AI原声翻译功能**,它能在翻译视频内容的同时,奇迹般地保留UP主独特的声线、音色和语气习惯 (o´ω'o)ノ。这项技术不仅解决了跨语言交流的生硬感,更通过[深度研究技术(AI资讯)](https://www.aibase.com/zh/news/20183)精准拿捏了游戏、二次元等领域的"行话”与"梗”,让文化出海之路变得既地道又充满人情味儿 🔥。这简直是为全球粉丝献上的一份原汁原味的大礼,确保了情感连接不会在翻译中"迷路”。 -
![AI资讯:B站AI翻译保留UP主音色](https://cdn.jsdmirror.com/gh/justlovemaki/imagehub@main/images/2025/08/news_01k1tshmx8frtvqqp1f9wwnrmn.avif) - -2. Figma开发者模式迎来史诗级更新,正式向设计师与开发者之间的"沟通地狱”宣战 (✧∀✧)!全新的**彩色交互式批注系统**,让交互逻辑、样式规范和无障碍需求一目了然,彻底告别了无休止的猜谜游戏。更具革命性的是,升级后的**MCP协议**能将设计系统的结构化数据直接喂给AI编码工具,这意味着AI生成的代码将前所未有地贴合设计稿,让[设计转代码的效率(AI资讯)](https://www.aibase.com/zh/news/20211)实现指数级暴增 🚀。 -
![AI资讯:Figma彩色批注系统](https://cdn.jsdmirror.com/gh/justlovemaki/imagehub@main/images/2025/08/news_01k1tshqr4f2wt2pwqfv42m12s.avif)
![AI资讯:Figma开发者模式更新](https://cdn.jsdmirror.com/gh/justlovemaki/imagehub@main/images/2025/08/news_01k1tshv8geg5at2md3331gqfc.avif) - -3. 米哈游联合创始人蔡浩宇亲自操刀的AI互动游戏**《星之低语》**,即将在Steam平台开启一场前所未有的情感实验 🌌。玩家将通过麦克风,与坠落在异星的宇航员Stella进行完全由AI驱动的开放式对话,你的每一句话都将直接影响她的命运。这款游戏彻底抛弃了传统对话树,旨在探索人机之间建立深层情感连接的可能性,正如[这份游戏前瞻(AI资讯)](https://www.aibase.com/zh/news/20184)所说,未来每个人都可能拥有一个数字灵魂伴侣 💡。 -
![AI资讯:米哈游AI游戏《星之低语》](https://cdn.jsdmirror.com/gh/justlovemaki/imagehub@main/images/2025/08/news_01k1tshxk8e2hb8cnx8e5gytwy.avif) \ No newline at end of file diff --git a/SECURITY.md b/server/SECURITY.md similarity index 100% rename from SECURITY.md rename to server/SECURITY.md diff --git a/check/check_doubao_voices.py b/server/check/check_doubao_voices.py similarity index 97% rename from check/check_doubao_voices.py rename to server/check/check_doubao_voices.py index e33ad30..1806246 100644 --- a/check/check_doubao_voices.py +++ b/server/check/check_doubao_voices.py @@ -6,8 +6,8 @@ import os import json def check_doubao_tts_voices(): - config_file_path = "config/doubao-tts.json" - tts_providers_path = "config/tts_providers.json" + config_file_path = "../config/doubao-tts.json" + tts_providers_path = "../config/tts_providers.json" test_text = "你好" # 测试文本 try: diff --git a/check/check_edgetts_voices.py b/server/check/check_edgetts_voices.py similarity index 100% rename from check/check_edgetts_voices.py rename to server/check/check_edgetts_voices.py diff --git a/check/check_fishaudio_voices.py b/server/check/check_fishaudio_voices.py similarity index 96% rename from check/check_fishaudio_voices.py rename to server/check/check_fishaudio_voices.py index ec9ae57..6a68e0a 100644 --- a/check/check_fishaudio_voices.py +++ b/server/check/check_fishaudio_voices.py @@ -5,8 +5,8 @@ import msgpack import json def check_fishaudio_voices(): - config_file_path = "config/fish-audio.json" - tts_providers_path = "config/tts_providers.json" + config_file_path = "../config/fish-audio.json" + tts_providers_path = "../config/tts_providers.json" test_text = "你好" # 测试文本 try: diff --git a/check/check_gemini_voices.py b/server/check/check_gemini_voices.py similarity index 97% rename from check/check_gemini_voices.py rename to server/check/check_gemini_voices.py index d75b7e6..a565c19 100644 --- a/check/check_gemini_voices.py +++ b/server/check/check_gemini_voices.py @@ -7,8 +7,8 @@ import base64 import json def check_gemini_voices(): - config_file_path = "config/gemini-tts.json" - tts_providers_path = "config/tts_providers.json" + config_file_path = "../config/gemini-tts.json" + tts_providers_path = "../config/tts_providers.json" test_text = "你好" # 测试文本 try: diff --git a/check/check_indextts_voices.py b/server/check/check_indextts_voices.py similarity index 100% rename from check/check_indextts_voices.py rename to server/check/check_indextts_voices.py diff --git a/check/check_minimax_voices.py b/server/check/check_minimax_voices.py similarity index 97% rename from check/check_minimax_voices.py rename to server/check/check_minimax_voices.py index 104e8d0..eab84e0 100644 --- a/check/check_minimax_voices.py +++ b/server/check/check_minimax_voices.py @@ -5,8 +5,8 @@ import os import json def check_minimax_voices(): - config_file_path = "config/minimax.json" - tts_providers_path = "config/tts_providers.json" + config_file_path = "../config/minimax.json" + tts_providers_path = "../config/tts_providers.json" test_text = "你好" # 测试文本 try: diff --git a/ext/doubao-voice-list.py b/server/ext/doubao-voice-list.py similarity index 100% rename from ext/doubao-voice-list.py rename to server/ext/doubao-voice-list.py diff --git a/ext/index-tts-api.py b/server/ext/index-tts-api.py similarity index 100% rename from ext/index-tts-api.py rename to server/ext/index-tts-api.py diff --git a/server/input.txt b/server/input.txt new file mode 100644 index 0000000..4b8a5a0 --- /dev/null +++ b/server/input.txt @@ -0,0 +1,59 @@ +```custom-begin +start with '欢迎收听来生小酒馆,客官不进来喝点吗?' , end with '感谢收听,下期再见' +不要自称主理人,馆长。说话符合人物角色设定。 +```custom-end + + + +### 产品与功能更新 + +1. DeepSeek V3.1 版本悄然上线,**上下文长度直接飙升至 128K**,处理十几万字的文档或整个代码库都变得轻而易举 (o´ω'o)ノ。本次升级不仅推理能力提升43%、幻觉减少38%,多语言支持也更上一层楼,唯一的美中不足是大家翘首以盼的R2模型仍是"犹抱琵琶半遮面”。现在就去[官网体验一下 - (AI资讯)](https://chat.deepseek.com/),感受超长文本的威力吧! + +2. 还在为复杂的图文视频生成流程头疼吗?Higgsfield AI 推出的 **Draw-to-Video** 功能让你彻底告别繁琐的文本提示词,只需在图片上画个箭头或圈圈,AI就能心领神会地生成电影级动态视频 🔥。这种"指哪打哪”的直观创作方式在外网迅速爆火,让视频创作的门槛又降低了一大截。快来[这里体验这份快乐 - (AI资讯)](https://higgsfield.ai/),让你的图片动起来!
![AI资讯:Higgsfield AI 的 Draw-to-Video 功能](https://image.jiqizhixin.com/uploads/editor/0416df91-9e5c-4677-ba53-a415ebe84ed1/640.gif) + +3. 小红书AIGC团队祭出大招,正式发布了名为 **DynamicFace 的可控人脸生成技术**,致力于解决图像和视频换脸中的老大难问题 🤔。这项技术的核心亮点在于"可控”与"高度一致性”,旨在消除视频换脸时常见的闪烁和不连贯感,为用户提供更精准、更个性的创作工具。正如[这篇(AI资讯)报道](https://www.aibase.com/zh/news/20613)所说,这是小红书在AI内容生成领域迈出的重要一步,让创意表达拥有了更多可能。 + +4. 英伟达发布了在排行榜上名列前茅的 **Nemotron Nano 2** 模型,这个仅 **9B 参数**的多语言推理小钢炮,正在重新定义AI的效率边界 🚀。它采用了独特的 **Transformer-Mamba 混合架构**,实现了比同类8B模型快6倍的吞吐量,同时通过"思考预算”机制将成本削减高达60%。想了解更多[技术细节可看这篇(AI资讯)](https://nvda.ws/3JfcKST),或者直接去[排行榜围观(AI资讯)](https://nvda.ws/47B7iUh),见证它的强大!
+ +5. Gemini API 迎来了一项超实用的更新,现在**直接支持对URL进行内容抓取**,无论是网页、PDF还是图片链接,统统可以一网打尽!这意味着开发者可以省去调用第三方抓取API的麻烦和费用,直接让模型处理网络上的实时内容,堪称是降本增效的一大利器 (✧∀✧)。快来[看看这篇(AI资讯)解读](https://x.com/dotey/status/1957579164363481114),了解如何用好这个新功能吧!
![AI资讯:Gemini API 抓取示例](https://pbs.twimg.com/media/Gyqd8opWIAMjgEU?format=jpg&name=orig) + +### 前沿研究 + +1. AI模型在理解图像时,会不会因为思维定式而"一叶障目”?一篇来自arXiv的[最新研究(AI资讯)](https://arxiv.org/abs/2404.10357)提出了**CoKnow框架**,通过引入多知识表征来优化提示学习,极大地丰富了模型的"视野”💡。简单说,它不再让模型只走一条路,而是给它提供了多种"知识视角”来分析问题,从而在11个公开数据集上超越了既有方法,让模型预测更准确。 + +2. 如何让AI不仅会说话,更能"共情”?一篇名为 E3RG 的[前沿论文(AI资讯)](https://arxiv.org/abs/2508.12854)提出了一种全新的多模态共情响应生成系统,将任务分解为**理解、记忆和生成**三部曲。该系统无需额外训练,就能生成包含丰富情感且身份一致的虚拟人形象,仿佛拥有了真正的"同理心”❤️。这项研究在ACM MM 25挑战赛中斩获头名,为构建更具人情味的人机交互开辟了新道路。 + +### 行业展望与社会影响 + +1. AI投资热潮之下,现实却有些骨感;麻省理工学院的一项研究发现,高达 **95% 的企业未能从其AI投入中获得任何回报**,总计约400亿美元的投资几乎打了水漂 💸。报告指出,"生成式AI鸿沟”的根源并非人才或资源匮乏,而是AI系统普遍缺乏记忆和适应能力,无法深度融入关键工作流程。正如[宝玉的这篇(AI资讯)分享](https://x.com/dotey/status/1957648622851428689)所言,成功的AI部署更像是建立深度合作关系,而非简单购买产品。 + +### 开源TOP项目 + +1. 腾讯为多模态和强化学习领域送上了一份大礼,正式开源了名为 **WeChat-YATT** 的大模型训练库,旨在解决两大核心瓶颈 🔥。通过创新的**并行控制器**机制和**异步交互**策略,它有效解决了多模态训练的可扩展性难题和动态采样下的效率短板,显著提升了GPU的利用率。想了解这一[开源利器的(AI资讯)详情](https://www.aibase.com/zh/news/20620),不妨深入看看官方发布的内容。
![AI资讯:腾讯开源WeChat-YATT训练库](https://upload.chinaz.com/2025/0819/6389120959924199577995616.png) + +2. 谷歌的Genie 3还在闭源,国产开源版世界模型 **Matrix-Game 2.0** 已经横空出世,在社区引发热议!这个仅 **1.8B 参数**的模型,能在单块GPU上以 **25FPS** 的帧率实时生成可交互的虚拟世界,你只需上传一张图片,就能在其中自由探索 (✧∀✧)。昆仑万维的这一开源力作,以其惊人的轻量化和高性能,为游戏开发和智能体训练开启了无限想象,快去[GitHub主页 - (AI资讯)](https://github.com/SkyworkAI/Matrix-Game)一探究竟吧。
![AI资讯:Matrix-Game 2.0 实时生成虚拟世界](https://image.jiqizhixin.com/uploads/editor/d7bfad6c-e613-40cf-8ec8-4bd9770615c8/640.gif)
![AI资讯:在Matrix-Game 2.0中探索GTA风格地图](https://image.jiqizhixin.com/uploads/editor/a3035e1c-ddbb-4f4b-ac4a-fc5e3f356816/640.gif) + +3. 想摆脱商业邮件服务商的月费"绑架”吗?**BillionMail** 这个在 [GitHub 上 ⭐8.9k 星的(AI资讯)项目](https://github.com/aaPanel/BillionMail) 为你提供了一站式开源解决方案,集邮件服务器、新闻通讯和邮件营销于一身。它完全支持自托管,对开发者极其友好,让你能以零月费的方式掌控自己的邮件系统,实现真正的数字独立 🚀。 + +4. 如果你是追求极致简约的音乐爱好者,那么在 [GitHub 上拥有 ⭐4.7k 星的 SPlayer(AI资讯)](https://github.com/imsyy/SPlayer) 绝对值得一试。这款播放器不仅界面清爽,还支持**逐字歌词、歌曲下载、音乐云盘管理**等强大功能,甚至还有酷炫的音乐频谱,堪称简约而不简单 (o´ω'o)ノ。它完美诠释了如何在小巧的体积中,容纳一个完整的音乐世界。 + +5. 对于那些对数字踪迹充满好奇的技术爱好者,[GitHub 上的 GhostTrack(AI资讯)](https://github.com/HunxByts/GhostTrack) 项目提供了一个用于追踪位置或手机号码的实用工具,已收获 ⭐1.9k 星。它就像一个数字世界的侦探工具,虽然用途广泛,但也提醒着我们在探索技术边界的同时,必须时刻关注隐私与伦理 🤔。 + +6. 让你的电脑拥有一个AI管家是怎样的体验?在 [GitHub 上收获 ⭐1.9k 星的 bytebot(AI资讯)](https://github.com/bytebot-ai/bytebot) 就是这样一个自托管的AI桌面代理,它能通过自然语言命令自动化执行电脑任务。它在安全的**容器化Linux环境**中运行,让你只需动动嘴,就能完成复杂操作,真正实现"君子动口不动手”的智能生活 🔥。 + +### 社媒分享 + +1. 进入AI领域不只需要懂代码和数学,软技能同样关键!吴恩达发布了一本免费的[职业指导电子书(AI资讯)](https://hubs.la/Q03DgNQ50),堪称是为AI求职者量身打造的"通关秘籍”💡。书中涵盖了**简历制作、面试技巧**,甚至还包括如何克服"冒名顶替综合症”,帮助你规划清晰的职业路线图,向心仪的工作迈进。
![AI资讯:吴恩达发布的免费电子书](https://pbs.twimg.com/media/Gyqx7K_W8AI4o8Z?format=jpg&name=orig) + +2. 在AI绘画中,提示词是不是越长越好?一位Reddit用户发出了灵魂拷问,他发现自己用二三十个词的短提示词,生成效果和别人几百词的长篇大论相差无几,甚至模型还会忽略大部分细节 🤔。这篇引发热议的[帖子 - (AI资讯)](https://old.reddit.com/r/FluxAI/comments/1mtyikj/whats_the_point_of_overly_long_prompts/)探讨了"长提示词”的实际意义,或许有时候,简洁才是通往好作品的捷径。 + +3. DeepSeek V3.1 的前端代码能力似乎又在"闷声发大财”了,有用户惊喜地发现,以前搞不定的一个复杂提示词,新版模型居然轻松拿捏,而且没有出现其他模型的字体大小问题 (✧∀✧)。这个在[社交媒体上的(AI资讯)发现](https://x.com/op7418/status/1957784895952155089),再次印证了官方宣布的 **128k 上下文**升级背后,是实打实的性能提升。
![AI资讯:Deepseek V3.1 官方更新通知](https://pbs.twimg.com/media/GytgxDKacAMVWfO?format=jpg&name=orig) + +4. 提示词工程也能成为一门艺术!用户李继刚分享了一段极具诗意的"视觉编织场”Prompt,用**光、张力、流**等充满美学的隐喻,指导AI将播客链接转化为设计感十足的可视化卡片 🎨。这种将设计哲学融入提示词的[高级玩法(AI资讯)](https://x.com/lijigang_com/status/1957756215653724324),展示了与AI沟通的全新境界,堪称一场人与机器的灵感共舞。
![AI资讯:李继刚的视觉编织场Prompt](https://pbs.twimg.com/media/GytY4-XacAQjMsJ?format=jpg&name=orig) + +5. 千问最新开源的图像编辑模型与FLUX Kontext的对决结果出炉!根据[博主的(AI资讯)评测](https://weibo.com/6182606334/Q0yOekb6d),千问模型的最大亮点在于其**独一无二的中文生成和编辑能力**,但图像美学和细节处理上则稍逊于FLUX,AI感较重。总的来说,它为中文内容创作提供了新利器,但想达到顶级效果可能还需社区的LoRA模型来"画龙点睛”✨。 + +6. OpenAI正在让顶级AI变得更亲民,**ChatGPT Go** 计划已在印度率先启动,每月订阅费仅需约4.55美元 🇮🇳!根据[Greg Brockman的(AI资讯)分享](https://x.com/gdb/status/1957650320923979996),该计划提供了比免费版**高10倍的消息量和图像生成量**,以及更长的记忆力。此举被视为AI普惠的重要一步,让更多人能以低成本享受强大AI工具带来的便利。 + +7. 想和孩子一起创作一本独一无二的故事书吗?Google Gemini 的 **Storybook** 功能让这一切变得简单有趣,正如[这篇(AI资讯)教程](https://x.com/shao__meng/status/1957605772017430917)所分享的,你可以上传照片作为灵感,指定**漫画或黏土动画**等艺术风格。这不仅是一个AI工具,更是一个激发家庭创造力、记录温馨回忆的互动平台 (o´ω'o)ノ。
![AI资讯:Google Gemini Storybook 使用技巧](https://pbs.twimg.com/media/GyrQEOLagAAz6OA?format=jpg&name=orig) + \ No newline at end of file diff --git a/main.py b/server/main.py similarity index 98% rename from main.py rename to server/main.py index 76fc73d..6d3db1a 100644 --- a/main.py +++ b/server/main.py @@ -74,7 +74,7 @@ stop_scheduler_event = threading.Event() # 全局配置 output_dir = "output" -time_after = 10 +time_after = 30 # 内存中存储任务结果 # {task_id: {"auth_id": auth_id, "status": TaskStatus, "result": any, "timestamp": float}} @@ -86,12 +86,12 @@ audio_file_mapping: Dict[str, Dict] = {} SECRET_KEY = os.getenv("PODCAST_API_SECRET_KEY", "your-super-secret-key") # 在生产环境中请务必修改! # 定义从 tts_provider 名称到其配置文件路径的映射 tts_provider_map = { - "index-tts": "config/index-tts.json", - "doubao-tts": "config/doubao-tts.json", - "edge-tts": "config/edge-tts.json", - "fish-audio": "config/fish-audio.json", - "gemini-tts": "config/gemini-tts.json", - "minimax": "config/minimax.json", + "index-tts": "../config/index-tts.json", + "doubao-tts": "../config/doubao-tts.json", + "edge-tts": "../config/edge-tts.json", + "fish-audio": "../config/fish-audio.json", + "gemini-tts": "../config/gemini-tts.json", + "minimax": "../config/minimax.json", } # 定义一个函数来清理输出目录 diff --git a/openai_cli.py b/server/openai_cli.py similarity index 100% rename from openai_cli.py rename to server/openai_cli.py diff --git a/podcast_generator.py b/server/podcast_generator.py similarity index 99% rename from podcast_generator.py rename to server/podcast_generator.py index e82677a..980b813 100644 --- a/podcast_generator.py +++ b/server/podcast_generator.py @@ -19,7 +19,7 @@ from tts_adapters import TTSAdapter, IndexTTSAdapter, EdgeTTSAdapter, FishAudioA # Global configuration output_dir = "output" file_list_path = os.path.join(output_dir, "file_list.txt") -tts_providers_config_path = 'config/tts_providers.json' +tts_providers_config_path = '../config/tts_providers.json' def read_file_content(filepath): """Reads content from a given file path.""" @@ -39,7 +39,7 @@ def _load_json_config(file_path: str) -> dict: except json.JSONDecodeError as e: raise ValueError(f"Error decoding JSON from {file_path}: {e}") -def select_json_config(config_dir='config', return_file_path=False): +def select_json_config(config_dir='../config', return_file_path=False): """ Reads JSON files from the specified directory and allows the user to select one. Returns the content of the selected JSON file. @@ -114,6 +114,7 @@ def generate_speaker_id_text(pod_users, voices_list): def merge_audio_files(): # 生成一个唯一的UUID unique_id = str(uuid.uuid4()) + unique_id = unique_id.replace("-", "") # 获取当前时间戳 timestamp = int(time.time()) # 组合UUID和时间戳作为文件名,去掉 'podcast_' 前缀 diff --git a/prompt/prompt-overview.txt b/server/prompt/prompt-overview.txt similarity index 100% rename from prompt/prompt-overview.txt rename to server/prompt/prompt-overview.txt diff --git a/prompt/prompt-podscript.txt b/server/prompt/prompt-podscript.txt similarity index 100% rename from prompt/prompt-podscript.txt rename to server/prompt/prompt-podscript.txt diff --git a/tts_adapters.py b/server/tts_adapters.py similarity index 100% rename from tts_adapters.py rename to server/tts_adapters.py diff --git a/web/src/app/api/audio/route.ts b/web/src/app/api/audio/route.ts index 3c49786..001f3c4 100644 --- a/web/src/app/api/audio/route.ts +++ b/web/src/app/api/audio/route.ts @@ -14,7 +14,7 @@ export async function GET(request: NextRequest) { } // 构建文件路径 - const outputDir = path.join(process.cwd(), '..', 'output'); + const outputDir = path.join(process.cwd(), '..', 'server', 'output'); const filePath = path.join(outputDir, filename); try { diff --git a/web/src/app/api/tts-providers/route.ts b/web/src/app/api/tts-providers/route.ts index 3fa72ee..b506acb 100644 --- a/web/src/app/api/tts-providers/route.ts +++ b/web/src/app/api/tts-providers/route.ts @@ -22,7 +22,11 @@ export async function GET() { } // 缓存无效或不存在,读取文件并更新缓存 - const configPath = path.join(process.cwd(), '..', 'config', 'tts_providers.json'); + const ttsProvidersName = process.env.TTS_PROVIDERS_NAME; + if (!ttsProvidersName) { + throw new Error('TTS_PROVIDERS_NAME 环境变量未设置'); + } + const configPath = path.join(process.cwd(), '..', 'config', ttsProvidersName); const configContent = await fs.readFile(configPath, 'utf-8'); const config = JSON.parse(configContent); diff --git a/web/src/app/layout.tsx b/web/src/app/layout.tsx index 024e2a1..bbbed9f 100644 --- a/web/src/app/layout.tsx +++ b/web/src/app/layout.tsx @@ -14,20 +14,24 @@ export const metadata: Metadata = { description: '使用AI技术将您的想法和内容转换为高质量的播客音频,支持多种语音和风格选择。', keywords: ['播客', 'AI', '语音合成', 'TTS', '音频生成'], authors: [{ name: 'PodcastHub Team' }], - viewport: 'width=device-width, initial-scale=1', - themeColor: '#000000', icons: { icon: '/favicon.webp', apple: '/favicon.webp', }, openGraph: { title: 'PodcastHub - 给创意一个真实的声音', - description: '使用AI技术将您的想法和内容转换为高质量的播客音频', + description: '使用AI技术将您的想法和内容转换为高质量的播客音频,支持多种语音和风格选择。', type: 'website', locale: 'zh_CN', }, }; +export const viewport = { + themeColor: '#000000', + width: 'device-width', + initialScale: 1, +}; + export default function RootLayout({ children, }: { diff --git a/web/src/components/PodcastContent.tsx b/web/src/components/PodcastContent.tsx index 339edda..c459744 100644 --- a/web/src/components/PodcastContent.tsx +++ b/web/src/components/PodcastContent.tsx @@ -100,7 +100,7 @@ export default async function PodcastContent({ fileName }: PodcastContentProps) {/* 标题 */} -

+

{audioInfo.title}

diff --git a/web/src/components/PodcastCreator.tsx b/web/src/components/PodcastCreator.tsx index d3556f8..867f5d6 100644 --- a/web/src/components/PodcastCreator.tsx +++ b/web/src/components/PodcastCreator.tsx @@ -157,17 +157,34 @@ const PodcastCreator: React.FC = ({
- - - + + + + + + + - - - - - - + + + + + + + + + + + + + + + + + + + diff --git a/web/src/components/Sidebar.tsx b/web/src/components/Sidebar.tsx index d083e27..e7e8090 100644 --- a/web/src/components/Sidebar.tsx +++ b/web/src/components/Sidebar.tsx @@ -139,21 +139,6 @@ const Sidebar: React.FC = ({ {/* 品牌名称容器 - 慢慢收缩动画 */}
- - - - - - - - - - - - - - - = ({ return (
= ({ onRemove, }) => { return ( -
{/* 定位到顶部水平居中,并限制宽度,使用flex布局垂直居中,增加间距 */} +
{/* 定位到顶部水平居中,并限制宽度,使用flex布局垂直居中,增加间距 */} {toasts.map((toast) => (