diff --git a/CLAUDE.md b/CLAUDE.md index 721427c..21e1dea 100644 --- a/CLAUDE.md +++ b/CLAUDE.md @@ -37,6 +37,7 @@ - **看板分析升级**(`寄存条_看板升级已外迁.md`):关键词——看板升级 / 双引擎象限图 / 题材热度 / AI 打标 / Prompt 1·2·3 / ground-truth / episodes 加字段 / 23 期回填 / 能力地图 / 置信度三档 / 本期诊断小结。 - **Doco 文稿整理**(`寄存条_doco子项目已外迁.md`):关键词——doco / 文稿整理 / 三方融合 / 视频双路拆分 / A·B 稿 / ASR / 讯飞 / DeepSeek Vision / 终版文稿 / 差异报告 / 段落对齐。**⚡ 2026-06-26 已交付:22 期融合A稿成品在 `doco/deliverables/`(按播出顺序命名),缺第01期(无A稿)。下一步:批量导入知识库(走 Phase 3 上传/embedding 链路)。** + - **CCA 唱词助手**(`寄存条CCA唱词助手子项目已外迁.md`):关键词——cca / 唱词助手 / changci / SRT 字幕 / 拍词规则 / 编导审稿台 / 唱词校对 / ASR 转字幕 / 大洋字幕格式 / 折行规则。**⚡ 2026-07-04 立项:编导 A 稿+人声音频 → ASR+AI 校对+编导审稿 → 大洋格式 SRT。先部署 lanhao 配音 2.0 测试,成熟后并入 TPS。** **主干仍管**:Phase 0–3 主干代码、全部 backend schema/API/迁移、全部前端 React 实施、主干 bug/性能/新需求、Cline 的全部 Plan+Act。 diff --git a/cca/.env.example b/cca/.env.example new file mode 100644 index 0000000..d4e7236 --- /dev/null +++ b/cca/.env.example @@ -0,0 +1,7 @@ +# 讯飞录音文件转写标准版(不是大模型版) +# 控制台: https://console.xfyun.cn/ +XFYUN_APP_ID=your_app_id +XFYUN_SECRET_KEY=your_secret_key + +# DeepSeek V4 Pro(用于专有名词提取 + 校对) +DEEPSEEK_API_KEY=your_deepseek_api_key diff --git a/cca/.gitignore b/cca/.gitignore new file mode 100644 index 0000000..d7e9800 --- /dev/null +++ b/cca/.gitignore @@ -0,0 +1,7 @@ +.env +output*/ +__pycache__/ +*.pyc +*.mp3 +*.wav +pr/ diff --git a/cca/CLAUDE.md b/cca/CLAUDE.md new file mode 100644 index 0000000..fa0925d --- /dev/null +++ b/cca/CLAUDE.md @@ -0,0 +1,147 @@ +# 项目协作主控文件 (cca/CLAUDE.md) + +--- + +## 🔖 状态栏 (STATUS — 每次结束 session 前必须更新这三行) + +- **最后更新**:Claude Code(动手开发)| 2026-07-04 +- **当前状态一句话**:脚本版流水线 v3 完成(绝对时间戳+严格校对不润色),等制片人周一大洋系统验证 SRT 导入效果。 +- **下一个动手的人从这里开始**:读完本文件,运行 `python cca_pipeline.py --help` 了解用法。凭证需填入 `cca/.env`(XFYUN + DEEPSEEK)。可选下一步:用 `--audio` 跑真实 ASR(带热词注入)看是否比缓存版效果更好。 + +--- + +## 🤖 给 AI 的工作约定 (READ FIRST) + +- 开始任何工作前,先读完本文件,特别是「状态栏」「交接备注」「关键决策」三节。 +- 完成一段工作后**增量更新**:「已完成」追加一条、「待办」勾掉或新增、必要时更新「关键决策」,最后改「状态栏」三行。不要重写整份文件,不要删历史,只追加/勾选。 +- 涉及发送、发布、删除、改权限、付款等不可逆操作前,先在对话里跟制片人确认。 +- **本项目着急用**——优先出可用版本,不追求完美架构。先跑通再优化。 +- **沟通**:全程简体中文;制片人不懂代码,解释说人话;给明确推荐不反复抛选项。 + +--- + +## 1. 项目概览 + +- **项目名**:CCA 唱词助手(ChangCi Assist)— 《军事科技》栏目编导/责编用的唱词字幕生成工具 +- **目标**:把编导 A 稿 + 粗编人声音频 → 经过 ASR + AI 校对 + 编导审稿 → 最终输出符合大洋系统的 SRT 字幕文件 +- **使用角色**:编导(提供 A 稿+音频、审稿确认)、责编(拿 SRT 拉到大洋上线) +- **部署计划**:先独立部署在 lanhao 配音 2.0 网站测试,成熟后吸收进 TPS 主项目作为子功能 + +### 核心工作流 + +``` +编导A稿 ──→ AI提取专有名词词典 + ↓ +粗编人声音频 + 词典 ──→ 讯飞ASR(录音文件转写标准版) ──→ 带时间戳ASR稿 + ↓ + ASR稿 ⊕ A稿 比对 + ↓ + ┌─ AI自动修正(明显错别字) + └─ 编导审稿台(拿不准的差异) + ↓ + B稿(定稿) + ↓ + 按拍词规则折行 + 时间戳 + ↓ + SRT文件(大洋格式) +``` + +--- + +## 2. 技术栈与运行方式 + +- **语言**:Python(与主项目 backend 对齐) +- **前端**:Web 界面(编导审稿台需要双屏对比 UI),技术选型待定(可复用主项目 React 或轻量方案) +- **ASR**:讯飞开放平台 录音文件转写标准版(已有 API Key,与 doco 共用同一套讯飞凭证) +- **AI**:LLM 用于两处——① 从 A 稿提取专有名词词典;② ASR 稿校对(的地得、引号、错别字) +- **输出格式**:SRT(大洋系统兼容格式,有样本参照) +- **美术风格**:参考 `ai-labeling/example/`(功能区划.jpg、幅面参考.jpg、页面风格.webp),与 TPS 主项目 UI 风格对齐 +- **凭证**:子项目自己 `.env`,不动主项目 `backend/.env` + +--- + +## 3. 当前进度 + +- **已完成至**:脚本版流水线 v3 跑通——绝对时间戳 + 严格校对(只改错别字/术语/填充词,不润色不调序)+ AI折行 + 5段SRT。 +- **正在做**:无,等制片人周一在大洋系统验证 SRT 导入效果。 +- **卡点/待解**:无硬卡点。可选优化:用 `--audio` 跑真实 ASR(热词注入生效)看是否在转写层就避免"建制→舰只"类错误。 + +--- + +## 4. 已完成(只追加,最新在上) + +- [2026-07-04] **脚本版流水线 v3(绝对时间戳+严格校对)**:① 恢复绝对时间戳(方便在大洋时间线对位);② 重写校对 Prompt——铁律:只改错别字/同音字、术语格式、口语填充词,绝不润色/调序/替换实词;③ 校对效果:60 处修正(vs v2 的 100 处,去掉了过度修改)。输出目录 `output_v3/`。 +- [2026-07-04] **脚本版流水线 v2 真实测试通过**:① 热词提取(规则+AI,127个术语)→ ② 讯飞ASR(94秒完成25MB音频,357句)→ ③ AI校对(DeepSeek,修正同音字/术语格式/口语填充,"建制"→"舰只"等)→ ④ AI折行(语义断句,98%行≤14字)→ ⑤ 5段SRT输出(段内相对时间戳,从00:00:00开始)。新增:hotword_extractor.py(热词提取)、ai_proofreader.py(AI校对)、ai_line_breaker.py(AI折行)。 +- [2026-07-04] 脚本版流水线骨架完成:① asr_client.py(讯飞ASR适配,从doco复用);② line_breaker.py(折行引擎,≤14字/语义断句/空白行检测);③ srt_writer.py(大洋格式SRT输出);④ segment_splitter.py(节目结构切分:导视/正片×3/预告);⑤ cca_pipeline.py(主入口串联全流程)。本地测试全部通过。 +- [2026-07-04] 子项目立项:目录结构、CLAUDE.md、Brief、主项目寄存条建立。 + +--- + +## 5. 待办(按优先级) + +- [x] ~~PRD / 业务规则确认~~ → 已在对话中完成(2026-07-04) +- [x] ~~脚本版流水线~~ → v3 完成(绝对时间戳+严格校对),等大洋验证 +- [x] ~~AI 校对层~~ → 已实现(两层防线:热词注入+DeepSeek 严格校对) +- [ ] **大洋系统验证**:周一导入 SRT 测试兼容性 +- [ ] **热词注入真实 ASR 测试**:用 `--audio` 跑完整流水线(非缓存),验证热词在转写层的效果 +- [ ] **编导审稿台**:双屏对比 UI、差异高亮、编导确认/手改交互(第二步) +- [ ] **部署至 lanhao 配音 2.0**:先跑起来测试 + +--- + +## 6. 关键决策(跨 session 最易丢) + +- [2026-07-04] **ASR 稿是权威底稿**:最终 SRT 必须和音频对应,ASR 稿(时间戳+内容)是基准。A 稿只提供专有名词写法和上下文参考,不能用 A 稿覆盖 ASR 的内容结构。 +- [2026-07-04] **讯飞用录音文件转写标准版**(与 doco 一样,不要大模型版)。热词偏置注入专有名词词典。 +- [2026-07-04] **编导审稿台是必要环节**:AI 拿不准的差异必须过编导确认,不能全自动。尊重编导创作主权(继承主项目设计哲学)。 +- [2026-07-04] **先独立部署再吸收**:先在 lanhao 配音 2.0 上跑通测试,成熟后并入 TPS 主项目。不等主项目进度。 +- [2026-07-04] **SRT 格式有样本**:data/ 下 3 个 SRT 是人工拍词导出的真实样本,作为格式参照。 +- [2026-07-04] **折行(拍词)规则**: + - A. 每行 ≤ 14 字 + - B. ASR 中 >2 秒空白 → 插入空白行(屏幕清字幕) + - C. 按语义断句(不机械凑满 14 字),符合阅读习惯 + - D. 去掉逗号/句号/感叹号等标点,只保留引号 +- [2026-07-04] **输出结构(5 个 SRT)**: + - 导视 1 个 + 正片 3 个 + 下期预告 1 个 + - 正片 3 个拆分依据:按时长大致均分,优先在角色转换处(解说词→专家采访)切分 + - 5 个 SRT 时间戳连续拼接 = 音频总长 +- [2026-07-04] **节目结构标志词**: + - 导视结束标志:听到"本期《军事科技》……" + - 正片开始标志:听到"各位观众你们好,我是主持人蓝皓" + - 正片结束标志:听到"好了观众朋友们,感谢您关注国防军事频道军事科技……" + - 正片之后是下期预告(无固定话术) +- [2026-07-04] **正片拆 3 个 SRT 的原因**:大洋字幕系统不稳定容易出错,责编提的需求。 +- [2026-07-04] **音频是纯人声**:已分离好的干净音频(无 BGM/音效),无需人声分离。 +- [2026-07-04] **先出脚本版**:命令行跑通流水线,审稿台第二步做。 +- [2026-07-04] **讯飞代码从 doco 复用**:`doco/src/doco/asr_adapter.py` 有完整签名/上传/轮询/解析逻辑,直接适配。 +- [2026-07-04] **SRT 用绝对时间戳**:每段 SRT 的时间戳是音频中的真实位置(不从 00:00:00 开始),方便在大洋时间线直接对位。制片人实测确认比相对时间戳好用。 +- [2026-07-04] **AI 校对严格纪律**:只允许改三类——① 错别字/同音字 ② 术语格式(F-15J)③ 口语填充词删除。绝不润色、绝不调序、绝不替换实词。ASR 是已录音频的转写,改不了内容。 +- [2026-07-04] **两层 ASR 纠错防线**:第一层=热词注入(预防,让讯飞在转写时就认对专有名词);第二层=AI 校对(修正,用 A 稿上下文判断同音字)。两层互补。 +- [2026-07-04] **LLM 选型已定**:校对+折行+热词提取统一用 DeepSeek(deepseek-chat),性价比最优。 + +--- + +## 7. ⏩ 交接备注 + +- **立项背景**:编导剪完节目后需要给责编一份 SRT 唱词字幕文件。传统流程是责编拿折行稿到大洋系统里 1:1 实时"拍词"(播放视频、听到对应句子拍空格记录时间戳),效率极低。CCA 用 ASR 自动化这个过程。 +- **"拍词"术语解释**:折行稿(去标点、按规则断行的文稿)+ 时间戳对位 = 拍词。传统靠人工实时听拍,CCA 用 ASR 时间戳代替。 +- **与 doco 的区别**:doco 是"播出后"整理终版文稿(三方融合);CCA 是"剪辑后、播出前"生成唱词字幕(ASR→校对→SRT)。两者共用讯飞 ASR 能力,但流程目的完全不同。 +- **数据样本**:`data/` 下有 A 稿 docx + mp3 音频 + 3 个人工拍词 SRT(对应正片三段)。 +- **代码文件**:`src/` 下是核心流水线代码(asr_client / line_breaker / ai_line_breaker / ai_proofreader / srt_writer / segment_splitter / hotword_extractor),入口 `cca_pipeline.py`。 +- **凭证**:需在 `cca/.env` 中填写 `XFYUN_APP_ID`、`XFYUN_SECRET_KEY`、`DEEPSEEK_API_KEY`。 +- **输出目录**:`output/`(ASR 缓存 + v1 输出)、`output_v2/`(相对时间戳版)、`output_v3/`(绝对时间戳+严格校对,当前最优)。 +- **运行命令示例**: + - 从缓存跑(调试校对/折行):`python -X utf8 cca_pipeline.py --asr-cache output/asr_raw.json --script "data/重走战争老路的日本军备(A稿).docx" --output-dir output_v3` + - 完整流水线(含真实 ASR):`python -X utf8 cca_pipeline.py --audio "data/重走战争老路的日本军备A0.mp3" --script "data/重走战争老路的日本军备(A稿).docx" --output-dir output_v4` +- **时间压力**:这两天要出可用版本,功能不复杂但要快。 + +--- + +## 8. 待确认 / 开放问题 + +- [x] ~~拍词规则~~ → 已确认(见关键决策) +- [x] ~~大洋 SRT 样本文件~~ → data/ 下已有 3 个真实样本 +- [x] ~~音频格式~~ → 纯人声 MP3,无需预处理 +- [x] ~~LLM 选型~~ → DeepSeek(deepseek-chat),已验证效果好、价格低 +- [ ] 前端审稿台技术选型(第二步再定) +- [ ] 大洋系统 SRT 导入兼容性(周一验证) diff --git a/cca/cca_pipeline.py b/cca/cca_pipeline.py new file mode 100644 index 0000000..63f3baf --- /dev/null +++ b/cca/cca_pipeline.py @@ -0,0 +1,152 @@ +# -*- coding: utf-8 -*- +""" +CCA 唱词助手 — 脚本版流水线入口 + +用法: + # 完整流程: A稿热词 + ASR + AI校对 + AI折行 → 5个SRT + python cca_pipeline.py --audio data/xxx.mp3 --script data/xxx.docx + + # 手动指定热词 + python cca_pipeline.py --audio data/xxx.mp3 --hotwords "热词1|热词2" + + # 跳过ASR,从缓存处理(调试折行/校对用) + python cca_pipeline.py --asr-cache output/asr_raw.json --script data/xxx.docx + + # 省token模式(不用AI折行和校对) + python cca_pipeline.py --asr-cache output/asr_raw.json --no-ai + +流水线: + A稿 → 热词提取 → 音频+热词 → 讯飞ASR → AI校对 → 节目结构切分 → AI折行 → 5个SRT +""" + +import argparse +import json +import os +import sys +from pathlib import Path + +sys.path.insert(0, str(Path(__file__).parent / "src")) + +from asr_client import transcribe, parse_result +from line_breaker import process_sentences +from ai_line_breaker import process_sentences_with_ai +from srt_writer import write_srt, ms_to_srt_time +from segment_splitter import split_into_segments +from hotword_extractor import extract_hotwords +from ai_proofreader import proofread_batch + + +def main(): + parser = argparse.ArgumentParser(description="CCA 唱词助手 - 自动生成拍词 SRT") + parser.add_argument("--audio", type=str, help="音频文件路径 (mp3/wav)") + parser.add_argument("--script", type=str, help="A稿路径 (.docx/.txt),用于热词提取和AI校对") + parser.add_argument("--hotwords", type=str, default="", help="手动指定热词,用|分隔(与--script可叠加)") + parser.add_argument("--asr-cache", type=str, help="ASR 缓存 JSON 路径(跳过ASR调用)") + parser.add_argument("--output-dir", type=str, default="output", help="输出目录 (默认: output/)") + parser.add_argument("--no-ai", action="store_true", help="不使用AI折行和校对(省token)") + parser.add_argument("--no-proofread", action="store_true", help="跳过AI校对(只省校对的token)") + args = parser.parse_args() + + if not args.audio and not args.asr_cache: + parser.error("必须提供 --audio 或 --asr-cache") + + output_dir = Path(args.output_dir) + output_dir.mkdir(parents=True, exist_ok=True) + use_ai = not args.no_ai + + # ====== Step 0: 热词提取(从A稿)====== + hot_words = [] + script_text = "" + + if args.hotwords: + hot_words = [w.strip() for w in args.hotwords.split("|") if w.strip()] + + if args.script: + print(f"[流水线] 从A稿提取热词: {args.script}") + script_hot = extract_hotwords(args.script, use_ai=use_ai) + # 合并手动热词和A稿热词 + seen = set(hot_words) + for w in script_hot: + if w not in seen: + hot_words.append(w) + seen.add(w) + + # 读取A稿全文(校对用) + ext = os.path.splitext(args.script)[1].lower() + if ext == ".docx": + from hotword_extractor import read_docx_text + script_text = read_docx_text(args.script) + else: + from hotword_extractor import read_text_file + script_text = read_text_file(args.script) + + if hot_words: + print(f"[流水线] 热词共 {len(hot_words)} 个: {', '.join(hot_words[:10])}...") + # 保存热词列表 + hotwords_path = output_dir / "hotwords.txt" + with open(hotwords_path, "w", encoding="utf-8") as f: + f.write("|".join(hot_words)) + + # ====== Step 1: ASR 转写 ====== + if args.asr_cache: + print(f"[流水线] 从缓存加载 ASR 结果: {args.asr_cache}") + with open(args.asr_cache, "r", encoding="utf-8") as f: + raw_json = f.read() + sentences = parse_result(raw_json) + else: + print(f"[流水线] 开始 ASR 转写: {args.audio}") + sentences, raw_json = transcribe(args.audio, hot_words=hot_words if hot_words else None) + + cache_path = output_dir / "asr_raw.json" + with open(cache_path, "w", encoding="utf-8") as f: + f.write(raw_json) + print(f"[流水线] ASR 原始结果已缓存: {cache_path}") + + print(f"[流水线] ASR 共 {len(sentences)} 句") + + # ====== Step 2: AI 校对 ====== + if use_ai and not args.no_proofread and script_text: + print("[流水线] AI 校对中 (DeepSeek)...") + sentences = proofread_batch(sentences, script_text) + elif not script_text and not args.no_proofread and use_ai: + print("[流水线] 未提供A稿(--script),跳过AI校对") + + # ====== Step 3: 节目结构切分 ====== + print("[流水线] 切分节目结构...") + segments = split_into_segments(sentences) + print(f"[流水线] 切分结果: {[name for name, _ in segments]}") + + # ====== Step 4: 折行 + 生成 SRT ====== + if use_ai: + print("[流水线] 使用 AI 折行 (DeepSeek)...") + else: + print("[流水线] 使用机械折行规则...") + + for seg_name, seg_sentences in segments: + if not seg_sentences: + print(f" [{seg_name}] 空段,跳过") + continue + + if use_ai: + subtitle_lines = process_sentences_with_ai(seg_sentences) + else: + subtitle_lines = process_sentences(seg_sentences) + + seg_offset = subtitle_lines[0][0] if subtitle_lines else 0 + seg_end = subtitle_lines[-1][1] if subtitle_lines else 0 + seg_duration = seg_end - seg_offset + + srt_filename = f"{seg_name}.srt" + srt_path = output_dir / srt_filename + write_srt(subtitle_lines, str(srt_path)) # 绝对时间戳,方便在时间线上对位 + print(f" [{seg_name}] 时长 {ms_to_srt_time(seg_duration)}, 在音频中的位置: {ms_to_srt_time(seg_offset)} ~ {ms_to_srt_time(seg_end)}") + + # ====== 完成 ====== + print(f"\n[流水线] 完成! 输出目录: {output_dir}/") + print("[流水线] 生成的文件:") + for f in sorted(output_dir.glob("*.srt")): + print(f" {f.name}") + + +if __name__ == "__main__": + main() diff --git a/cca/data/1.srt b/cca/data/1.srt new file mode 100644 index 0000000..e4fd82e --- /dev/null +++ b/cca/data/1.srt @@ -0,0 +1,1292 @@ +1 +00:00:08,520 --> 00:00:08,840 + + +2 +00:00:08,880 --> 00:00:09,880 +各位观众你们好 + +3 +00:00:09,920 --> 00:00:11,320 +欢迎收看《军事科技》 + +4 +00:00:11,360 --> 00:00:12,280 +我是主持人蓝皓 + +5 +00:00:12,320 --> 00:00:13,120 + + +6 +00:00:13,160 --> 00:00:14,400 +日本国会参议院 + +7 +00:00:14,440 --> 00:00:16,000 +今天上午(6月26日)表决通过了 + +8 +00:00:16,040 --> 00:00:18,480 +防卫省设置法修正案等法案 + +9 +00:00:18,520 --> 00:00:20,080 +决定将航空自卫队 + +10 +00:00:20,120 --> 00:00:22,320 +改编为航空宇宙自卫队 + +11 +00:00:22,360 --> 00:00:24,320 +这是日本自1954年 + +12 +00:00:24,360 --> 00:00:29,040 +成立陆上 海上 航空自卫队以来 + +13 +00:00:29,080 --> 00:00:30,320 +由于相关法案已于四月底 + +14 +00:00:30,360 --> 00:00:31,000 +这意味着 + +15 +00:00:31,040 --> 00:00:33,040 +日本将放弃战争 + +16 +00:00:33,080 --> 00:00:34,360 +不维持军事力量 + +17 +00:00:34,400 --> 00:00:36,000 +并否认交战权 + +18 +00:00:36,040 --> 00:00:37,440 + + +19 +00:00:37,480 --> 00:00:39,280 +79年时光荏苒 + +20 +00:00:39,320 --> 00:00:40,680 +现今的日本自卫队 + +21 +00:00:40,720 --> 00:00:41,560 +已经装备了 + +22 +00:00:41,600 --> 00:00:43,000 +大型水面舰艇 + +23 +00:00:43,040 --> 00:00:44,320 +远程巡航导弹 + +24 +00:00:44,360 --> 00:00:45,920 +与高超音速武器 + +25 +00:00:45,960 --> 00:00:47,760 +甚至着手向海外 + +26 +00:00:47,800 --> 00:00:50,000 +输出致命装备 + +27 +00:00:50,040 --> 00:00:50,600 +这一切 + +28 +00:00:50,640 --> 00:00:52,880 +是如何演变的呢 + +29 +00:00:52,920 --> 00:00:53,320 +今日 + +30 +00:00:53,360 --> 00:00:54,480 +我们将剖析这一 + +31 +00:00:54,520 --> 00:00:56,240 +邪祟附体的历程 + +32 +00:00:56,280 --> 00:00:57,720 +审视日本怎样凭借 + +33 +00:00:57,760 --> 00:01:00,080 +一层又一层防御的言辞 + +34 +00:01:00,120 --> 00:01:01,760 +将进攻性的猛兽 + +35 +00:01:01,800 --> 00:01:04,840 +包裹进和平的伪装之中 + +36 +00:01:04,880 --> 00:01:07,040 + + +37 +00:01:07,080 --> 00:01:08,960 +对于战后日本而言 + +38 +00:01:09,000 --> 00:01:10,800 +重新武装最大的限制 + +39 +00:01:10,840 --> 00:01:11,880 +不是工业能力 + +40 +00:01:11,920 --> 00:01:13,760 +而是政治约束 + +41 +00:01:13,800 --> 00:01:15,800 +作为一个长期受“和平宪法” + +42 +00:01:15,840 --> 00:01:18,240 +和“专守防卫”原则约束的国家 + +43 +00:01:18,280 --> 00:01:20,840 +相比于周期漫长的自主研发 + +44 +00:01:20,880 --> 00:01:23,160 +直接从海外采购成熟装备 + +45 +00:01:23,200 --> 00:01:25,160 +既能快速形成战斗力 + +46 +00:01:25,200 --> 00:01:26,560 +也能在一定程度上 + +47 +00:01:26,600 --> 00:01:27,560 +降低国内外 + +48 +00:01:27,600 --> 00:01:29,840 +对其军事扩张的关注 + +49 +00:01:29,880 --> 00:01:30,480 +因此 + +50 +00:01:30,520 --> 00:01:32,440 +从冷战时期到今天 + +51 +00:01:32,480 --> 00:01:34,680 +大规模引进美国武器装备 + +52 +00:01:34,720 --> 00:01:35,680 +始终是日本 + +53 +00:01:35,720 --> 00:01:37,080 +提升军事实力的 + +54 +00:01:37,120 --> 00:01:38,160 +重要途径 + +55 +00:01:38,200 --> 00:01:40,640 + + +56 +00:01:40,680 --> 00:01:42,280 +20世纪50年代 + +57 +00:01:42,320 --> 00:01:44,360 +日本自卫队刚刚成立时 + +58 +00:01:44,400 --> 00:01:45,840 +军事力量的重建 + +59 +00:01:45,880 --> 00:01:48,760 +几乎是从美国仓库里开始的 + +60 +00:01:48,800 --> 00:01:50,480 +进入冷战后期 + +61 +00:01:50,520 --> 00:01:53,160 +日本采购的规模越来越大 + +62 +00:01:53,200 --> 00:01:54,480 +1981年 + +63 +00:01:54,520 --> 00:01:55,360 +日本引进 + +64 +00:01:55,400 --> 00:01:57,160 +F-15J战斗机 + +65 +00:01:57,200 --> 00:01:59,160 +凭借强大的空战性能 + +66 +00:01:59,200 --> 00:02:00,120 +这款战机 + +67 +00:02:00,160 --> 00:02:03,320 +迅速成为日本航空自卫队的主力 + +68 +00:02:03,360 --> 00:02:04,880 +此后数十年间 + +69 +00:02:04,920 --> 00:02:06,000 +日本共装备 + +70 +00:02:06,040 --> 00:02:07,160 +超过两百架 + +71 +00:02:07,200 --> 00:02:08,960 +F-15系列战斗机 + +72 +00:02:09,000 --> 00:02:10,760 +构成日本领空防御的 + +73 +00:02:10,800 --> 00:02:11,880 +核心力量 + +74 +00:02:11,920 --> 00:02:14,200 + + +75 +00:02:14,240 --> 00:02:16,080 +而进入21世纪后 + +76 +00:02:16,120 --> 00:02:17,920 +日本采购武器的性质 + +77 +00:02:17,960 --> 00:02:19,680 +开始发生变化 + +78 +00:02:19,720 --> 00:02:20,880 +过去购买的 + +79 +00:02:20,920 --> 00:02:22,240 +是防空武器 + +80 +00:02:22,280 --> 00:02:23,240 +反潜装备 + +81 +00:02:23,280 --> 00:02:24,800 +和拦截系统 + +82 +00:02:24,840 --> 00:02:26,080 +如今购买的 + +83 +00:02:26,120 --> 00:02:27,160 +却是越来越多 + +84 +00:02:27,200 --> 00:02:30,320 +具备远程打击能力的平台 + +85 +00:02:30,360 --> 00:02:31,480 +2011年 + +86 +00:02:31,520 --> 00:02:32,760 +日本决定引进 + +87 +00:02:32,800 --> 00:02:35,200 +F-35隐身战斗机 + +88 +00:02:35,240 --> 00:02:35,880 +此后 + +89 +00:02:35,920 --> 00:02:37,120 +日本先后采购 + +90 +00:02:37,160 --> 00:02:39,240 +147架F-35A + +91 +00:02:39,280 --> 00:02:40,560 +和F-35B + +92 +00:02:40,600 --> 00:02:41,720 +成为美国之外 + +93 +00:02:41,760 --> 00:02:44,240 +最大的F-35用户之一 + +94 +00:02:44,280 --> 00:02:45,320 +2015年 + +95 +00:02:45,360 --> 00:02:46,240 +美国国务院 + +96 +00:02:46,280 --> 00:02:47,680 +批准向日本军售 + +97 +00:02:47,720 --> 00:02:51,360 +RQ-4全球鹰高空长航时无人机 + +98 +00:02:51,400 --> 00:02:52,440 +这种无人机 + +99 +00:02:52,480 --> 00:02:53,920 +翼展接近40米 + +100 +00:02:53,960 --> 00:02:55,200 +单次飞行时间 + +101 +00:02:55,240 --> 00:02:56,720 +超过30小时 + +102 +00:02:56,760 --> 00:02:58,320 +能够在数万米高空 + +103 +00:02:58,360 --> 00:03:01,120 +持续执行战略侦察任务 + +104 +00:03:01,160 --> 00:03:02,720 +2020年以后 + +105 +00:03:02,760 --> 00:03:03,320 +日本 + +106 +00:03:03,360 --> 00:03:04,480 +又陆续引进 + +107 +00:03:04,520 --> 00:03:07,320 +V-22鱼鹰倾转旋翼机 + +108 +00:03:07,360 --> 00:03:09,000 +这种能够像直升机一样 + +109 +00:03:09,040 --> 00:03:10,120 +垂直起降 + +110 +00:03:10,160 --> 00:03:10,800 +又能够像 + +111 +00:03:10,840 --> 00:03:11,920 +固定翼飞机一样 + +112 +00:03:11,960 --> 00:03:14,240 +高速飞行的特殊飞行器 + +113 +00:03:14,280 --> 00:03:15,080 +使日本 + +114 +00:03:15,120 --> 00:03:16,640 +拥有了更远距离的 + +115 +00:03:16,680 --> 00:03:18,640 +快速机动能力 + +116 +00:03:18,680 --> 00:03:20,040 +而变化最大的 + +117 +00:03:20,080 --> 00:03:21,600 +则是导弹 + +118 +00:03:21,640 --> 00:03:23,000 +2023年底 + +119 +00:03:23,040 --> 00:03:24,280 +日本正式决定 + +120 +00:03:24,320 --> 00:03:26,960 +采购美国战斧巡航导弹 + +121 +00:03:27,000 --> 00:03:27,960 +这种导弹 + +122 +00:03:28,000 --> 00:03:30,360 +射程超过1600公里 + +123 +00:03:30,400 --> 00:03:32,400 +从设计诞生的第一天起 + +124 +00:03:32,440 --> 00:03:33,920 +它就不是为海岸防御 + +125 +00:03:33,960 --> 00:03:35,160 +准备的武器 + +126 +00:03:35,200 --> 00:03:37,800 +它的使命是远程打击 + +127 +00:03:37,840 --> 00:03:38,800 + + +128 +00:03:38,840 --> 00:03:40,080 +日本一直在寻求 + +129 +00:03:40,120 --> 00:03:41,320 +从一个经济大国 + +130 +00:03:41,360 --> 00:03:42,640 +向政治大国 + +131 +00:03:42,680 --> 00:03:44,200 +乃至一个军事大国 + +132 +00:03:44,240 --> 00:03:46,040 +进行转型 + +133 +00:03:46,080 --> 00:03:48,160 +但是在转型的过程中间 + +134 +00:03:48,200 --> 00:03:49,480 +实际上日本有一个 + +135 +00:03:49,520 --> 00:03:50,280 +根本性的问题 + +136 +00:03:50,320 --> 00:03:51,880 +他绕不开他是 + +137 +00:03:51,920 --> 00:03:54,840 +第二次世界大战的战败国 + +138 +00:03:54,880 --> 00:03:55,680 +“和平宪法” + +139 +00:03:55,720 --> 00:03:57,000 +对他的军事力量的发展 + +140 +00:03:57,040 --> 00:03:59,040 +实际上是构成了 + +141 +00:03:59,080 --> 00:04:00,760 +非常重要的约束 + +142 +00:04:00,800 --> 00:04:02,440 +那么在这个过程中间 + +143 +00:04:02,480 --> 00:04:04,920 +他在军力不断地发展的时候 + +144 +00:04:04,960 --> 00:04:07,400 +实际上他采取了两个措施 + +145 +00:04:07,440 --> 00:04:11,160 +来帮助他发展军力 + +146 +00:04:11,200 --> 00:04:12,400 +特别是发展一些 + +147 +00:04:12,440 --> 00:04:13,600 +进攻性的力量 + +148 +00:04:13,640 --> 00:04:14,920 +这两个措施 + +149 +00:04:14,960 --> 00:04:16,320 +第一个实际上 + +150 +00:04:16,360 --> 00:04:17,960 +就是渲染威胁 + +151 +00:04:18,000 --> 00:04:20,440 +第二个是防御伪装 + +152 +00:04:20,480 --> 00:04:23,080 +这就是为他发展军力 + +153 +00:04:23,120 --> 00:04:25,800 +特别是发展一些进攻性的力量 + +154 +00:04:25,840 --> 00:04:27,680 +在制造一个所谓的 + +155 +00:04:27,720 --> 00:04:30,120 +合理性的借口 + +156 +00:04:30,160 --> 00:04:31,360 +他把一些这种 + +157 +00:04:31,400 --> 00:04:32,640 +进攻性的力量 + +158 +00:04:32,680 --> 00:04:34,320 +实际上包装到 + +159 +00:04:34,360 --> 00:04:36,000 +防御的范畴里面 + +160 +00:04:36,040 --> 00:04:38,320 +也就是在反击能力中间 + +161 +00:04:38,360 --> 00:04:39,880 +把进攻性的力量 + +162 +00:04:39,920 --> 00:04:41,080 +包装成了一种 + +163 +00:04:41,120 --> 00:04:42,360 +防御性的手段 + +164 +00:04:42,400 --> 00:04:44,840 +日本在发展军事力量的 + +165 +00:04:44,880 --> 00:04:45,840 +过程中间 + +166 +00:04:45,880 --> 00:04:46,800 +最近这几年 + +167 +00:04:46,840 --> 00:04:48,320 +特别强调发展 + +168 +00:04:48,360 --> 00:04:50,680 +远程精确 + +169 +00:04:50,720 --> 00:04:52,920 +和综合的态势感知 + +170 +00:04:52,960 --> 00:04:53,920 +这方面的能力 + +171 +00:04:53,960 --> 00:04:55,440 +在这个领域 + +172 +00:04:55,480 --> 00:04:56,920 +在发展的过程中间 + +173 +00:04:56,960 --> 00:04:58,200 +他始终强调一个 + +174 +00:04:58,240 --> 00:05:01,560 +先寻求与美国进行勾连 + +175 +00:05:01,600 --> 00:05:03,240 +然后再寻求 + +176 +00:05:03,280 --> 00:05:05,880 +实现日本的发展 + +177 +00:05:05,920 --> 00:05:07,640 +那么向美国采购 + +178 +00:05:07,680 --> 00:05:09,200 +就是他实现 + +179 +00:05:09,240 --> 00:05:10,160 +他进攻性力量 + +180 +00:05:10,200 --> 00:05:11,720 +和广域态势感知中间 + +181 +00:05:11,760 --> 00:05:13,520 +一个非常重要的 + +182 +00:05:13,560 --> 00:05:15,000 +一种策略性的选择 + +183 +00:05:15,040 --> 00:05:17,240 +就是他向美国进行采购 + +184 +00:05:17,280 --> 00:05:18,680 +从美国进行引进以后 + +185 +00:05:18,720 --> 00:05:19,680 +在某种程度上 + +186 +00:05:19,720 --> 00:05:21,800 +一方面可以让他快速地 + +187 +00:05:21,840 --> 00:05:22,960 +拥有这种能力 + +188 +00:05:23,000 --> 00:05:23,560 +另外 + +189 +00:05:23,600 --> 00:05:24,640 +有美国的背书 + +190 +00:05:24,680 --> 00:05:25,280 + + +191 +00:05:25,320 --> 00:05:26,560 +日本通过从美国 + +192 +00:05:26,600 --> 00:05:28,360 +引进F-35战机 + +193 +00:05:28,400 --> 00:05:29,960 +和战斧巡航导弹等 + +194 +00:05:30,000 --> 00:05:30,960 +先进装备 + +195 +00:05:31,000 --> 00:05:31,840 +迅速获得了 + +196 +00:05:31,880 --> 00:05:33,080 +第五代战机 + +197 +00:05:33,120 --> 00:05:34,560 +远程精确打击能力 + +198 +00:05:34,600 --> 00:05:35,040 +以及 + +199 +00:05:35,080 --> 00:05:36,680 +先进导弹防御系统等 + +200 +00:05:36,720 --> 00:05:38,320 +现代化战力 + +201 +00:05:38,360 --> 00:05:38,840 +然而 + +202 +00:05:38,880 --> 00:05:40,160 +采购终究是 + +203 +00:05:40,200 --> 00:05:42,040 +获得现成的武器 + +204 +00:05:42,080 --> 00:05:43,000 +对于日本来说 + +205 +00:05:43,040 --> 00:05:44,240 +更关键的目标 + +206 +00:05:44,280 --> 00:05:45,040 +在于掌握 + +207 +00:05:45,080 --> 00:05:46,560 +核心武器装备的 + +208 +00:05:46,600 --> 00:05:47,800 +自主研制 + +209 +00:05:47,840 --> 00:05:50,480 +与升级技术 + +210 +00:05:50,520 --> 00:05:51,160 +因此 + +211 +00:05:51,200 --> 00:05:53,280 +在大量购入美国武器的同时 + +212 +00:05:53,320 --> 00:05:54,720 +日本也在持续推动 + +213 +00:05:54,760 --> 00:05:57,120 +本国国防工业体系的建设 + +214 +00:05:57,160 --> 00:05:57,720 +其中 + +215 +00:05:57,760 --> 00:05:59,120 +两个方面的变化 + +216 +00:05:59,160 --> 00:06:00,200 +值得关注 + +217 +00:06:00,240 --> 00:06:01,160 + + +218 +00:06:01,200 --> 00:06:04,240 +一是导弹射程的扩展 + +219 +00:06:04,280 --> 00:06:06,120 +原本以近海防御为主的 + +220 +00:06:06,160 --> 00:06:07,680 +12式反舰导弹 + +221 +00:06:07,720 --> 00:06:08,800 +其打击距离 + +222 +00:06:08,840 --> 00:06:09,840 +在不断延长 + +223 +00:06:09,880 --> 00:06:10,880 +作战定位 + +224 +00:06:10,920 --> 00:06:13,040 +也在相应改变 + +225 +00:06:13,080 --> 00:06:13,640 +二是 + +226 +00:06:13,680 --> 00:06:16,200 +海上平台的转型 + +227 +00:06:16,240 --> 00:06:17,600 +作为日本海上自卫队 + +228 +00:06:17,640 --> 00:06:19,600 +最大的水面舰艇之一 + +229 +00:06:19,640 --> 00:06:20,840 +出云级 + +230 +00:06:20,880 --> 00:06:22,040 +正在进行改装 + +231 +00:06:22,080 --> 00:06:25,200 +以适应F-35B战机的起降 + +232 +00:06:25,240 --> 00:06:27,440 +这艘曾被称为护卫舰的舰艇 + +233 +00:06:27,480 --> 00:06:28,720 +正在逐步获得 + +234 +00:06:28,760 --> 00:06:31,240 +运用固定翼舰载机的能力 + +235 +00:06:31,280 --> 00:06:36,200 + + +236 +00:06:36,240 --> 00:06:37,800 +12式反舰导弹 + +237 +00:06:37,840 --> 00:06:40,000 +是日本陆上自卫队装备的 + +238 +00:06:40,040 --> 00:06:42,960 +新一代岸基反舰导弹系统 + +239 +00:06:43,000 --> 00:06:43,840 +主要用于 + +240 +00:06:43,880 --> 00:06:45,520 +对海上舰艇目标 + +241 +00:06:45,560 --> 00:06:47,880 +实施远程精确打击 + +242 +00:06:47,920 --> 00:06:49,800 +导弹长度约5米 + +243 +00:06:49,840 --> 00:06:52,080 +弹径约350毫米 + +244 +00:06:52,120 --> 00:06:54,320 +发射重量约700公斤 + +245 +00:06:54,360 --> 00:06:56,560 +采用固体火箭助推器 + +246 +00:06:56,600 --> 00:06:57,600 +巡航阶段 + +247 +00:06:57,640 --> 00:06:59,840 +使用涡喷发动机推进 + +248 +00:06:59,880 --> 00:07:02,480 +飞行速度约马赫数0.9 + +249 +00:07:02,520 --> 00:07:04,280 +原始型号最大射程 + +250 +00:07:04,320 --> 00:07:05,640 +约200公里 + +251 +00:07:05,680 --> 00:07:06,680 +12式导弹 + +252 +00:07:06,720 --> 00:07:08,760 +采用复合制导方式 + +253 +00:07:08,800 --> 00:07:10,440 +导弹飞行过程中 + +254 +00:07:10,480 --> 00:07:12,360 +能够根据外部目标信息 + +255 +00:07:12,400 --> 00:07:13,960 +进行航路修正 + +256 +00:07:14,000 --> 00:07:14,640 +末段 + +257 +00:07:14,680 --> 00:07:15,920 +具备自主搜索 + +258 +00:07:15,960 --> 00:07:17,560 +和目标识别能力 + +259 +00:07:17,600 --> 00:07:18,360 +近年来 + +260 +00:07:18,400 --> 00:07:19,160 +日本启动 + +261 +00:07:19,200 --> 00:07:22,200 +12式导弹能力向上型研发计划 + +262 +00:07:22,240 --> 00:07:23,040 +该型号 + +263 +00:07:23,080 --> 00:07:25,240 +是日本远程打击体系建设的 + +264 +00:07:25,280 --> 00:07:26,360 +重要项目 + +265 +00:07:26,400 --> 00:07:28,280 +首先是射程提升 + +266 +00:07:28,320 --> 00:07:29,200 +由原来的 + +267 +00:07:29,240 --> 00:07:30,360 +约200公里 + +268 +00:07:30,400 --> 00:07:32,800 +提升至约1000公里以上 + +269 +00:07:32,840 --> 00:07:33,560 +其次是 + +270 +00:07:33,600 --> 00:07:34,920 +隐身外形 + +271 +00:07:34,960 --> 00:07:37,000 +将弹体重新设计 + +272 +00:07:37,040 --> 00:07:39,200 +减少雷达反射截面积 + +273 +00:07:39,240 --> 00:07:41,400 +新增对陆精确打击能力 + +274 +00:07:41,440 --> 00:07:42,320 + + +275 +00:07:42,360 --> 00:07:43,000 +然而 + +276 +00:07:43,040 --> 00:07:45,600 +即便是射程达到上千公里的 + +277 +00:07:45,640 --> 00:07:48,000 +12式能力向上型导弹 + +278 +00:07:48,040 --> 00:07:50,000 +也并非日本远程打击体系 + +279 +00:07:50,040 --> 00:07:51,560 +建设的终点 + +280 +00:07:51,600 --> 00:07:52,520 +近年来 + +281 +00:07:52,560 --> 00:07:54,200 +日本正将更多资源 + +282 +00:07:54,240 --> 00:07:55,280 +投入到另一类 + +283 +00:07:55,320 --> 00:07:56,920 +武器的发展之中 + +284 +00:07:56,960 --> 00:07:58,720 +高超音速滑翔弹 + +285 +00:07:58,760 --> 00:08:00,360 +与传统导弹相比 + +286 +00:08:00,400 --> 00:08:01,800 +高超音速滑翔弹 + +287 +00:08:01,840 --> 00:08:02,880 +最大的特点 + +288 +00:08:02,920 --> 00:08:04,440 +在于速度更快 + +289 +00:08:04,480 --> 00:08:06,400 +飞行轨迹更加复杂 + +290 +00:08:06,440 --> 00:08:07,400 +拦截难度 + +291 +00:08:07,440 --> 00:08:09,640 +也随之大幅提高 + +292 +00:08:09,680 --> 00:08:11,000 +它被普遍认为是 + +293 +00:08:11,040 --> 00:08:13,200 +未来远程精确打击体系的 + +294 +00:08:13,240 --> 00:08:15,040 +重要组成部分 + +295 +00:08:15,080 --> 00:08:17,400 +也是当前世界主要军事强国 + +296 +00:08:17,440 --> 00:08:19,920 +竞相发展的重点项目之一 + +297 +00:08:19,960 --> 00:08:21,160 + + +298 +00:08:21,200 --> 00:08:21,800 +近日 + +299 +00:08:21,840 --> 00:08:23,120 +日本陆上自卫队 + +300 +00:08:23,160 --> 00:08:25,440 +在静冈县东富士演习场 + +301 +00:08:25,480 --> 00:08:27,280 +举行了国内最大规模的 + +302 +00:08:27,320 --> 00:08:29,600 +富士综合火力演习 + +303 +00:08:29,640 --> 00:08:31,240 +并首次公开展示了 + +304 +00:08:31,280 --> 00:08:32,920 +射程约1000公里的 + +305 +00:08:32,960 --> 00:08:35,040 +25式高超声速导弹 + +306 +00:08:35,080 --> 00:08:36,080 + + +307 +00:08:36,120 --> 00:08:37,000 +6月8日 + +308 +00:08:37,040 --> 00:08:38,120 +日本防卫省 + +309 +00:08:38,160 --> 00:08:39,640 +开始将陆上自卫队 + +310 +00:08:39,680 --> 00:08:42,520 +12式岸舰导弹发射装置等装备 + +311 +00:08:42,560 --> 00:08:44,160 +部署至日本最东端 + +312 +00:08:44,200 --> 00:08:45,320 +离岛南鸟岛 + +313 +00:08:45,360 --> 00:08:47,560 +并计划自2027年起 + +314 +00:08:47,600 --> 00:08:51,600 +在当地开展实弹射击训练 + +315 +00:08:51,640 --> 00:08:53,880 +日方在军事安全领域危险 + +316 +00:08:53,920 --> 00:08:54,480 +冒进 + +317 +00:08:54,520 --> 00:08:55,320 +和试探 + +318 +00:08:55,360 --> 00:08:57,000 +挑衅动作频频 + +319 +00:08:57,040 --> 00:08:58,000 +早已戳穿了 + +320 +00:08:58,040 --> 00:08:59,200 +其和平国家 + +321 +00:08:59,240 --> 00:09:01,400 +和专守防卫的自我标榜 + +322 +00:09:01,440 --> 00:09:04,040 + + +323 +00:09:04,080 --> 00:09:04,080 + + diff --git a/cca/data/2.srt b/cca/data/2.srt new file mode 100644 index 0000000..e687455 --- /dev/null +++ b/cca/data/2.srt @@ -0,0 +1,1252 @@ +1 +00:00:00,280 --> 00:00:02,200 +目前日本在发展 + +2 +00:00:02,240 --> 00:00:03,880 +进攻性力量这个方面 + +3 +00:00:03,920 --> 00:00:05,920 +它是以日本相对来讲 + +4 +00:00:05,960 --> 00:00:08,880 +比较成熟的一型导弹 + +5 +00:00:08,920 --> 00:00:11,240 +主要就是12式反舰导弹 + +6 +00:00:11,280 --> 00:00:12,960 +以此为基础 + +7 +00:00:13,000 --> 00:00:15,600 +不断地进行迭代升级 + +8 +00:00:15,640 --> 00:00:17,200 +形成日本的这种 + +9 +00:00:17,240 --> 00:00:19,840 +远程精确打击能力 + +10 +00:00:19,880 --> 00:00:21,760 +所以从12式 + +11 +00:00:21,800 --> 00:00:24,200 +这种导弹的能力向上型 + +12 +00:00:24,240 --> 00:00:27,440 +和这种高超声速的(滑空)弹 + +13 +00:00:27,480 --> 00:00:29,240 +这两个发展情况来看的话 + +14 +00:00:29,280 --> 00:00:31,400 +日本是在构建一个 + +15 +00:00:31,440 --> 00:00:33,280 +利用日本的成熟技术 + +16 +00:00:33,320 --> 00:00:37,080 +来发展远程的打击能力 + +17 +00:00:37,120 --> 00:00:38,720 +而且这种远程打击能力 + +18 +00:00:38,760 --> 00:00:40,200 +是这种亚音速 + +19 +00:00:40,240 --> 00:00:42,960 +和高超声速结合 + +20 +00:00:43,000 --> 00:00:45,440 +射程覆盖战略纵深 + +21 +00:00:45,480 --> 00:00:46,640 +到战役纵深的 + +22 +00:00:46,680 --> 00:00:48,360 +精确打击的能力 + +23 +00:00:48,400 --> 00:00:49,840 +那么它反映出来 + +24 +00:00:49,880 --> 00:00:52,760 +日本现在正在构建一个 + +25 +00:00:52,800 --> 00:00:54,400 +由美国提供的 + +26 +00:00:54,440 --> 00:00:56,280 +或者说向美国采购的 + +27 +00:00:56,320 --> 00:00:58,240 +远程精确打击武器 + +28 +00:00:58,280 --> 00:01:00,200 +再加上日本自研的 + +29 +00:01:00,240 --> 00:01:02,800 +多种远程精确打击武器结合 + +30 +00:01:02,840 --> 00:01:04,520 +构成的一个所谓的 + +31 +00:01:04,560 --> 00:01:07,160 +具有反击能力的作战体系 + +32 +00:01:07,200 --> 00:01:09,360 +在2026年3月份 + +33 +00:01:09,400 --> 00:01:10,280 +日本陆上自卫队 + +34 +00:01:10,320 --> 00:01:12,040 +第一阶段部署 + +35 +00:01:12,080 --> 00:01:14,480 +12式导弹的能力向上型的时候 + +36 +00:01:14,520 --> 00:01:15,640 +它选择的点位 + +37 +00:01:15,680 --> 00:01:17,000 +就是熊本县 + +38 +00:01:17,040 --> 00:01:18,560 +那么在正式的 + +39 +00:01:18,600 --> 00:01:20,560 +第一阶段部署之后就把 + +40 +00:01:20,600 --> 00:01:23,080 +12式导弹的能力向上型 + +41 +00:01:23,120 --> 00:01:25,320 +已经正式的把它型号 + +42 +00:01:25,360 --> 00:01:27,680 +改成25式导弹了 + +43 +00:01:27,720 --> 00:01:29,000 +所以从这个情况 + +44 +00:01:29,040 --> 00:01:30,520 +就可以看到 + +45 +00:01:30,560 --> 00:01:33,240 +12式导弹的这种能力向上型 + +46 +00:01:33,280 --> 00:01:34,680 +已经是日本 + +47 +00:01:34,720 --> 00:01:37,360 +陆上自卫队目前装备的最新型的 + +48 +00:01:37,400 --> 00:01:40,000 +一型远程攻击性的武器 + +49 +00:01:40,040 --> 00:01:41,800 +在熊本县部署的时候 + +50 +00:01:41,840 --> 00:01:42,840 +这一型的武器 + +51 +00:01:42,880 --> 00:01:43,560 +如果是在 + +52 +00:01:43,600 --> 00:01:45,800 +900到1000千米的时候 + +53 +00:01:45,840 --> 00:01:47,360 +东海基本上 + +54 +00:01:47,400 --> 00:01:49,680 +被这一型的导弹是覆盖的 + +55 +00:01:49,720 --> 00:01:50,720 +中国东部 + +56 +00:01:50,760 --> 00:01:52,880 +非常重要的一个沿海城市 + +57 +00:01:52,920 --> 00:01:54,000 +上海 + +58 +00:01:54,040 --> 00:01:55,680 +其实就是在它的 + +59 +00:01:55,720 --> 00:01:56,800 +打击范围里面 + +60 +00:01:56,840 --> 00:01:58,000 +所以日本 + +61 +00:01:58,040 --> 00:01:58,680 +第一阶段 + +62 +00:01:58,720 --> 00:02:00,600 +选择熊本县部署 + +63 +00:02:00,640 --> 00:02:01,760 +这个居心 + +64 +00:02:01,800 --> 00:02:04,200 +我们就可以看得很清楚 + +65 +00:02:04,240 --> 00:02:05,840 +在世界海军中 + +66 +00:02:05,880 --> 00:02:07,000 +主流护卫舰 + +67 +00:02:07,040 --> 00:02:09,160 +通常承担舰队护航 + +68 +00:02:09,200 --> 00:02:10,200 +反潜巡逻 + +69 +00:02:10,240 --> 00:02:11,920 +和区域警戒任务 + +70 +00:02:11,960 --> 00:02:12,960 +德国海军的 + +71 +00:02:13,000 --> 00:02:15,000 +巴登-符腾堡级护卫舰 + +72 +00:02:15,040 --> 00:02:17,240 +舰长约149米 + +73 +00:02:17,280 --> 00:02:20,200 +满载排水量约7200吨 + +74 +00:02:20,240 --> 00:02:21,680 +舰体中部和前部 + +75 +00:02:21,720 --> 00:02:22,840 +布置雷达 + +76 +00:02:22,880 --> 00:02:25,640 +导弹垂直发射系统和舰炮 + +77 +00:02:25,680 --> 00:02:26,320 +舰艉 + +78 +00:02:26,360 --> 00:02:28,560 +设置直升机甲板与机库 + +79 +00:02:28,600 --> 00:02:30,480 +搭载一到两架直升机 + +80 +00:02:30,520 --> 00:02:32,800 +以满足反潜与侦察需求 + +81 +00:02:32,840 --> 00:02:35,240 + + +82 +00:02:35,280 --> 00:02:38,160 +然而在日本海上自卫队的序列中 + +83 +00:02:38,200 --> 00:02:39,760 +有一类舰艇的名称 + +84 +00:02:39,800 --> 00:02:41,640 +一直颇具争议 + +85 +00:02:41,680 --> 00:02:42,960 +日本称它们为 + +86 +00:02:43,000 --> 00:02:44,960 +直升机护卫舰 + +87 +00:02:45,000 --> 00:02:46,720 +早在2009年 + +88 +00:02:46,760 --> 00:02:48,200 +日本海上自卫队 + +89 +00:02:48,240 --> 00:02:49,000 +便迎来了 + +90 +00:02:49,040 --> 00:02:50,240 +日向级首舰 + +91 +00:02:50,280 --> 00:02:51,760 +日向号服役 + +92 +00:02:51,800 --> 00:02:52,600 +两年后 + +93 +00:02:52,640 --> 00:02:53,880 +二号舰伊势号 + +94 +00:02:53,920 --> 00:02:55,280 +加入舰队 + +95 +00:02:55,320 --> 00:02:56,280 +即便是被称为 + +96 +00:02:56,320 --> 00:02:57,920 +世界最大护卫舰之一的 + +97 +00:02:57,960 --> 00:02:59,880 +巴登-符腾堡级护卫舰 + +98 +00:02:59,920 --> 00:03:00,720 +排水量 + +99 +00:03:00,760 --> 00:03:01,760 +也仅相当于 + +100 +00:03:01,800 --> 00:03:03,280 +日向级的一半左右 + +101 +00:03:03,320 --> 00:03:04,320 + + +102 +00:03:04,360 --> 00:03:06,440 +按照日本防卫省的解释 + +103 +00:03:06,480 --> 00:03:07,880 +日向级的主要任务 + +104 +00:03:07,920 --> 00:03:09,240 +是反潜作战 + +105 +00:03:09,280 --> 00:03:10,400 +海上警戒 + +106 +00:03:10,440 --> 00:03:11,480 +舰队指挥 + +107 +00:03:11,520 --> 00:03:13,360 +以及灾害救援 + +108 +00:03:13,400 --> 00:03:15,480 +但无论从哪个角度观察 + +109 +00:03:15,520 --> 00:03:16,760 +人们都很难把它 + +110 +00:03:16,800 --> 00:03:18,520 +与传统意义上的护卫舰 + +111 +00:03:18,560 --> 00:03:19,920 +联系起来 + +112 +00:03:19,960 --> 00:03:21,600 +全通式飞行甲板 + +113 +00:03:21,640 --> 00:03:23,560 +右舷岛式上层建筑 + +114 +00:03:23,600 --> 00:03:25,280 +宽阔的机库空间 + +115 +00:03:25,320 --> 00:03:27,040 +以及接近航空母舰的 + +116 +00:03:27,080 --> 00:03:28,360 +舰体布局 + +117 +00:03:28,400 --> 00:03:31,640 + + +118 +00:03:31,680 --> 00:03:33,880 +该级舰共建造两艘 + +119 +00:03:33,920 --> 00:03:37,280 +满载排水量约19000吨 + +120 +00:03:37,320 --> 00:03:39,240 +舰长197米 + +121 +00:03:39,280 --> 00:03:41,040 +舰宽33米 + +122 +00:03:41,080 --> 00:03:43,440 +最高航速约30节 + +123 +00:03:43,480 --> 00:03:45,800 +续航力约8000海里 + +124 +00:03:45,840 --> 00:03:47,120 +动力系统采用 + +125 +00:03:47,160 --> 00:03:49,680 +4台LM-2500燃气轮机 + +126 +00:03:49,720 --> 00:03:51,920 +总功率约10万马力 + +127 +00:03:51,960 --> 00:03:52,680 +舰体 + +128 +00:03:52,720 --> 00:03:55,080 +采用全通式飞行甲板设计 + +129 +00:03:55,120 --> 00:03:57,760 +共设置4个直升机起降点 + +130 +00:03:57,800 --> 00:03:58,920 +机库面积 + +131 +00:03:58,960 --> 00:04:00,760 +约3500平方米 + +132 +00:04:00,800 --> 00:04:01,520 +可搭载 + +133 +00:04:01,560 --> 00:04:04,240 +SH-60K反潜直升机 + +134 +00:04:04,280 --> 00:04:07,240 +MCH-101扫雷直升机 + +135 +00:04:07,280 --> 00:04:08,280 +舰载武器 + +136 +00:04:08,320 --> 00:04:09,640 +包括16单元 + +137 +00:04:09,680 --> 00:04:11,920 +MK-41垂直发射系统 + +138 +00:04:11,960 --> 00:04:14,200 +ESSM舰空导弹 + +139 +00:04:14,240 --> 00:04:16,120 +阿斯洛克反潜导弹 + +140 +00:04:16,160 --> 00:04:18,640 +20毫米密集阵近防系统 + +141 +00:04:18,680 --> 00:04:19,640 +舰载雷达 + +142 +00:04:19,680 --> 00:04:23,160 +采用FCS-3A有源相控阵雷达 + +143 +00:04:23,200 --> 00:04:24,600 +具备同时搜索 + +144 +00:04:24,640 --> 00:04:26,240 +跟踪和制导能力 + +145 +00:04:26,280 --> 00:04:34,320 + + +146 +00:04:34,360 --> 00:04:36,840 +日向级直升机护卫舰 + +147 +00:04:36,880 --> 00:04:39,360 +日本在发展的过程中间 + +148 +00:04:39,400 --> 00:04:42,600 +他对军舰的这种归类 + +149 +00:04:42,640 --> 00:04:44,800 +他把大型的水面舰只 + +150 +00:04:44,840 --> 00:04:46,840 +归结为护卫舰 + +151 +00:04:46,880 --> 00:04:48,840 +实际上这是日本 + +152 +00:04:48,880 --> 00:04:51,560 +这种所谓的防御包装 + +153 +00:04:51,600 --> 00:04:52,360 +或者说 + +154 +00:04:52,400 --> 00:04:54,960 +防御伪装的一种称呼 + +155 +00:04:55,000 --> 00:04:56,160 +实际上 + +156 +00:04:56,200 --> 00:04:58,240 +日向级这一型的军舰 + +157 +00:04:58,280 --> 00:04:59,080 +某种意义上来讲 + +158 +00:04:59,120 --> 00:05:00,440 +它就是准航母 + +159 +00:05:00,480 --> 00:05:01,200 +但是 + +160 +00:05:01,240 --> 00:05:01,960 +在日本的 + +161 +00:05:02,000 --> 00:05:03,720 +武器装备的归类中间 + +162 +00:05:03,760 --> 00:05:05,120 +把它归置为 + +163 +00:05:05,160 --> 00:05:06,960 +直升机护卫舰 + +164 +00:05:07,000 --> 00:05:07,680 +我们知道 + +165 +00:05:07,720 --> 00:05:09,360 +在护卫舰归类的时候 + +166 +00:05:09,400 --> 00:05:10,280 +通常情况下 + +167 +00:05:10,320 --> 00:05:12,360 +是一个中型的军舰 + +168 +00:05:12,400 --> 00:05:13,920 +但是 + +169 +00:05:13,960 --> 00:05:15,440 +日本把日向级 + +170 +00:05:15,480 --> 00:05:17,160 +把它包装成所谓的 + +171 +00:05:17,200 --> 00:05:18,600 +直升机护卫舰 + +172 +00:05:18,640 --> 00:05:21,200 +实际上就是以这种形式 + +173 +00:05:21,240 --> 00:05:22,480 +来对它这样一个 + +174 +00:05:22,520 --> 00:05:24,320 +带有比较浓厚的 + +175 +00:05:24,360 --> 00:05:26,880 +攻击性色彩的武器 + +176 +00:05:26,920 --> 00:05:29,880 +包装成一个所谓的防御性的 + +177 +00:05:29,920 --> 00:05:32,520 +以护卫舰这种形式 + +178 +00:05:32,560 --> 00:05:34,320 +把它包装成所谓的防御性(舰艇) + +179 +00:05:34,360 --> 00:05:36,040 +但是不管它叫什么名字 + +180 +00:05:36,080 --> 00:05:36,880 +实际上 + +181 +00:05:36,920 --> 00:05:38,000 +它在性质上 + +182 +00:05:38,040 --> 00:05:39,720 +就是一个准航母 + +183 +00:05:39,760 --> 00:05:40,080 +所以 + +184 +00:05:40,120 --> 00:05:43,920 +发展日向级直升机护卫舰 + +185 +00:05:43,960 --> 00:05:45,000 +其实日本 + +186 +00:05:45,040 --> 00:05:46,760 +所想达到的目的 + +187 +00:05:46,800 --> 00:05:49,120 +我认为可能有三个方面 + +188 +00:05:49,160 --> 00:05:50,440 +第一个就是 + +189 +00:05:50,480 --> 00:05:54,360 +突破“和平宪法”的限制 + +190 +00:05:54,400 --> 00:05:57,040 +实现了所谓的准航母化 + +191 +00:05:57,080 --> 00:05:58,880 +这一点是 + +192 +00:05:58,920 --> 00:06:00,800 +全世界都看得清清楚楚 + +193 +00:06:00,840 --> 00:06:02,440 +不管日本人怎么包装 + +194 +00:06:02,480 --> 00:06:04,280 +不管日本人(把装备)叫什么名字 + +195 +00:06:04,320 --> 00:06:06,400 +本质上都摆脱不了 + +196 +00:06:06,440 --> 00:06:08,400 +第二个是构建 + +197 +00:06:08,440 --> 00:06:10,040 +以准航母为核心的 + +198 +00:06:10,080 --> 00:06:13,240 +远海反潜作战编队 + +199 +00:06:13,280 --> 00:06:15,280 +第三个目的就是日本 + +200 +00:06:15,320 --> 00:06:17,240 +他想以日向级 + +201 +00:06:17,280 --> 00:06:18,920 +这艘军舰为基础 + +202 +00:06:18,960 --> 00:06:20,600 +为未来发展 + +203 +00:06:20,640 --> 00:06:24,040 +大中型的这种航母 + +204 +00:06:24,080 --> 00:06:26,680 +实际上奠定一个技术基础 + +205 +00:06:26,720 --> 00:06:28,200 + + +206 +00:06:28,240 --> 00:06:29,720 +从舰载机调度 + +207 +00:06:29,760 --> 00:06:31,280 +到飞行甲板管理 + +208 +00:06:31,320 --> 00:06:32,600 +从航空保障 + +209 +00:06:32,640 --> 00:06:34,040 +到指挥协同 + +210 +00:06:34,080 --> 00:06:35,680 +日本在这艘舰艇上 + +211 +00:06:35,720 --> 00:06:37,280 +积累着大型甲板舰 + +212 +00:06:37,320 --> 00:06:38,600 +运用经验 + +213 +00:06:38,640 --> 00:06:39,880 +许多只存在于 + +214 +00:06:39,920 --> 00:06:42,040 +旧日本海军历史中的能力 + +215 +00:06:42,080 --> 00:06:44,920 +开始重新回到现实之中 + +216 +00:06:44,960 --> 00:06:46,080 +而当这些经验 + +217 +00:06:46,120 --> 00:06:47,400 +逐渐成熟后 + +218 +00:06:47,440 --> 00:06:49,320 +一艘更大 更长 + +219 +00:06:49,360 --> 00:06:51,680 +航空保障能力更强的新舰 + +220 +00:06:51,720 --> 00:06:53,920 +开始进入建造阶段 + +221 +00:06:53,960 --> 00:06:55,200 +2015年 + +222 +00:06:55,240 --> 00:06:56,760 +出云号服役 + +223 +00:06:56,800 --> 00:06:57,920 +2017年 + +224 +00:06:57,960 --> 00:07:00,400 +加贺号服役 + +225 +00:07:00,440 --> 00:07:02,160 +与日向级相比 + +226 +00:07:02,200 --> 00:07:04,040 +出云级飞行甲板面积 + +227 +00:07:04,080 --> 00:07:05,280 +进一步扩大 + +228 +00:07:05,320 --> 00:07:07,480 +机库空间更加宽裕 + +229 +00:07:07,520 --> 00:07:08,520 +航空燃料 + +230 +00:07:08,560 --> 00:07:09,920 +和弹药储备能力 + +231 +00:07:09,960 --> 00:07:12,400 +也得到明显增强 + +232 +00:07:12,440 --> 00:07:13,720 +从外观上看 + +233 +00:07:13,760 --> 00:07:14,920 +它依旧保留着 + +234 +00:07:14,960 --> 00:07:17,440 +直升机护卫舰的官方称谓 + +235 +00:07:17,480 --> 00:07:19,320 +但从设计思路来看 + +236 +00:07:19,360 --> 00:07:20,240 +出云级 + +237 +00:07:20,280 --> 00:07:21,600 +已经不再满足于 + +238 +00:07:21,640 --> 00:07:22,960 +执行反潜巡逻 + +239 +00:07:23,000 --> 00:07:24,520 +和灾害救援任务 + +240 +00:07:24,560 --> 00:07:26,560 + + +241 +00:07:26,600 --> 00:07:27,520 +出云级 + +242 +00:07:27,560 --> 00:07:29,120 +是日本海上自卫队 + +243 +00:07:29,160 --> 00:07:30,520 +目前吨位最大的 + +244 +00:07:30,560 --> 00:07:32,240 +水面作战舰艇 + +245 +00:07:32,280 --> 00:07:33,760 +共建造两艘 + +246 +00:07:33,800 --> 00:07:34,680 +出云号 + +247 +00:07:34,720 --> 00:07:36,080 +加贺号 + +248 +00:07:36,120 --> 00:07:38,960 +满载排水量约27000吨 + +249 +00:07:39,000 --> 00:07:41,080 +舰长248米 + +250 +00:07:41,120 --> 00:07:43,040 +舰宽38米 + +251 +00:07:43,080 --> 00:07:45,160 +吃水约7.5米 + +252 +00:07:45,200 --> 00:07:47,680 +最高航速约30节 + +253 +00:07:47,720 --> 00:07:48,720 +动力系统 + +254 +00:07:48,760 --> 00:07:49,760 +采用4台 + +255 +00:07:49,800 --> 00:07:54,000 +LM-2500IEC燃气轮机 + +256 +00:07:54,040 --> 00:07:55,480 +飞行甲板面积 + +257 +00:07:55,520 --> 00:07:57,600 +超过13000平方米 + +258 +00:07:57,640 --> 00:07:58,680 +机库面积 + +259 +00:07:58,720 --> 00:08:00,480 +约5600平方米 + +260 +00:08:00,520 --> 00:08:03,760 +可搭载最多约28架航空器 + +261 +00:08:03,800 --> 00:08:04,360 +舰上 + +262 +00:08:04,400 --> 00:08:06,640 +设有两部大型升降机 + +263 +00:08:06,680 --> 00:08:07,840 +能够同时保障 + +264 +00:08:07,880 --> 00:08:10,000 +多架航空器的起降和维护 + +265 +00:08:10,040 --> 00:08:12,040 + + +266 +00:08:12,080 --> 00:08:14,880 +其实这个日向和出云 + +267 +00:08:14,920 --> 00:08:16,880 +这在旧日本海军中间 + +268 +00:08:16,920 --> 00:08:21,600 +也是两艘非常重要的舰只 + +269 +00:08:21,640 --> 00:08:23,120 +首先我们可以看 + +270 +00:08:23,160 --> 00:08:24,360 +出云 + +271 +00:08:24,400 --> 00:08:26,120 +出云这一艘军舰 + +272 +00:08:26,160 --> 00:08:27,320 +在旧日本海军中间 + +273 +00:08:27,360 --> 00:08:29,560 +实际上它服役时间是比较长的 + +274 +00:08:29,600 --> 00:08:31,560 +1900年就已经 + +275 +00:08:31,600 --> 00:08:33,800 +加入到了旧日本海军 + +276 +00:08:33,840 --> 00:08:34,920 +但是我们 + +277 +00:08:34,960 --> 00:08:37,840 +对出云这一艘舰只 + +278 +00:08:37,880 --> 00:08:39,600 +对于我们中国人来讲的话 + +279 +00:08:39,640 --> 00:08:41,160 +必须要牢记一点 + +280 +00:08:41,200 --> 00:08:43,080 +它在侵华战争中间 + +281 +00:08:43,120 --> 00:08:46,200 +这是一艘罪行累累的军舰 + +282 +00:08:46,240 --> 00:08:48,000 +那么这艘军舰 + +283 +00:08:48,040 --> 00:08:50,600 +最终是在1945年的时候 + +284 +00:08:50,640 --> 00:08:53,400 +由于它的整个的功能都下降 + +285 +00:08:53,440 --> 00:08:54,600 +最后它是在 + +286 +00:08:54,640 --> 00:08:55,640 +它的港口里面 + +287 +00:08:55,680 --> 00:08:57,160 +把它转型成一艘 + +288 +00:08:57,200 --> 00:08:59,440 +防空的这种炮台 + +289 +00:08:59,480 --> 00:09:00,360 +在这个过程中间 + +290 +00:09:00,400 --> 00:09:02,760 +被美国飞机击中 + +291 +00:09:02,800 --> 00:09:04,840 +最后沉没了 + +292 +00:09:04,880 --> 00:09:05,480 +日向号 + +293 +00:09:05,520 --> 00:09:07,160 +要比出云号的服役时间 + +294 +00:09:07,200 --> 00:09:08,040 +稍短一点 + +295 +00:09:08,080 --> 00:09:08,840 +它是在 + +296 +00:09:08,880 --> 00:09:11,000 +1917(年)到1918年的时候 + +297 +00:09:11,040 --> 00:09:12,560 +加入旧日本海军 + +298 +00:09:12,600 --> 00:09:14,320 +在中途岛海战中间 + +299 +00:09:14,360 --> 00:09:15,600 +日本先后有4艘 + +300 +00:09:15,640 --> 00:09:17,720 +航空母舰都被美国击沉了 + +301 +00:09:17,760 --> 00:09:20,640 +日本的航空母舰存在着 + +302 +00:09:20,680 --> 00:09:22,200 +数量急缺 + +303 +00:09:22,240 --> 00:09:23,440 +那么在这种情况之下 + +304 +00:09:23,480 --> 00:09:25,040 +想把它改造成一个 + +305 +00:09:25,080 --> 00:09:26,920 +轻型的航母 + +306 +00:09:26,960 --> 00:09:28,440 +但是改造的过程实际上 + +307 +00:09:28,480 --> 00:09:30,600 +并不是那么特别地顺利 + +308 +00:09:30,640 --> 00:09:33,200 +最后也是被美国的飞机 + +309 +00:09:33,240 --> 00:09:36,040 +在港口中间将它击沉 + +310 +00:09:36,080 --> 00:09:38,000 +所以沉到海底 + +311 +00:09:38,040 --> 00:09:41,360 +都是日向和出云 + +312 +00:09:41,400 --> 00:09:44,240 +这两艘军舰最后的归宿 + +313 +00:09:44,280 --> 00:09:44,280 + + diff --git a/cca/data/3.srt b/cca/data/3.srt new file mode 100644 index 0000000..85dcf25 --- /dev/null +++ b/cca/data/3.srt @@ -0,0 +1,1112 @@ +1 +00:00:00,960 --> 00:00:01,200 + + +2 +00:00:01,240 --> 00:00:03,040 +如果仔细观察日向级 + +3 +00:00:03,080 --> 00:00:05,120 +与出云级的舰体设计 + +4 +00:00:05,160 --> 00:00:06,040 +就会发现一个 + +5 +00:00:06,080 --> 00:00:08,040 +非常值得关注的变化 + +6 +00:00:08,080 --> 00:00:11,200 +那就是武器系统的取舍 + +7 +00:00:11,240 --> 00:00:12,600 +作为日本战后的 + +8 +00:00:12,640 --> 00:00:15,440 +第一型大型全通甲板舰艇 + +9 +00:00:15,480 --> 00:00:16,280 +日向级 + +10 +00:00:16,320 --> 00:00:17,240 +虽然被称为 + +11 +00:00:17,280 --> 00:00:18,840 +直升机护卫舰 + +12 +00:00:18,880 --> 00:00:20,240 +但它的设计思路 + +13 +00:00:20,280 --> 00:00:21,040 +仍然延续着 + +14 +00:00:21,080 --> 00:00:23,560 +传统驱逐舰的作战理念 + +15 +00:00:23,600 --> 00:00:24,640 +舰上安装了 + +16 +00:00:24,680 --> 00:00:25,520 +16单元 + +17 +00:00:25,560 --> 00:00:27,880 +MK-41垂直发射系统 + +18 +00:00:27,920 --> 00:00:29,480 +可以发射反潜导弹 + +19 +00:00:29,520 --> 00:00:31,000 +和舰空导弹 + +20 +00:00:31,040 --> 00:00:32,960 +同时保留鱼雷发射管 + +21 +00:00:33,000 --> 00:00:33,560 +然而 + +22 +00:00:33,600 --> 00:00:34,760 +到了出云级 + +23 +00:00:34,800 --> 00:00:36,680 +情况发生了变化 + +24 +00:00:36,720 --> 00:00:38,200 +这艘大型舰艇 + +25 +00:00:38,240 --> 00:00:40,440 +并没有继续增加导弹数量 + +26 +00:00:40,480 --> 00:00:41,400 +反而取消了 + +27 +00:00:41,440 --> 00:00:43,600 +日向级上的垂直发射系统 + +28 +00:00:43,640 --> 00:00:45,440 +和鱼雷发射管 + +29 +00:00:45,480 --> 00:00:46,520 +取而代之的 + +30 +00:00:46,560 --> 00:00:47,920 +是更大的机库 + +31 +00:00:47,960 --> 00:00:50,160 +更完善的航空保障设施 + +32 +00:00:50,200 --> 00:00:52,320 +以及更加宽阔的飞行甲板 + +33 +00:00:52,360 --> 00:00:53,840 + + +34 +00:00:53,880 --> 00:00:55,400 +自2020年起 + +35 +00:00:55,440 --> 00:00:56,280 +出云级 + +36 +00:00:56,320 --> 00:00:58,520 +开始实施航母化改装 + +37 +00:00:58,560 --> 00:01:01,360 +首先是飞行甲板耐热强化 + +38 +00:01:01,400 --> 00:01:03,760 +F-35B垂直降落时 + +39 +00:01:03,800 --> 00:01:05,200 +发动机尾喷温度 + +40 +00:01:05,240 --> 00:01:07,280 +超过1500摄氏度 + +41 +00:01:07,320 --> 00:01:07,840 +因此 + +42 +00:01:07,880 --> 00:01:10,840 +需要重新铺设耐热甲板材料 + +43 +00:01:10,880 --> 00:01:11,600 +其次是 + +44 +00:01:11,640 --> 00:01:13,200 +舰艏改造 + +45 +00:01:13,240 --> 00:01:14,840 +将原有梯形舰艏 + +46 +00:01:14,880 --> 00:01:16,680 +改为矩形舰艏 + +47 +00:01:16,720 --> 00:01:18,880 +增加起飞滑跑距离 + +48 +00:01:18,920 --> 00:01:19,680 +最后是 + +49 +00:01:19,720 --> 00:01:21,960 +航空保障设施升级 + +50 +00:01:22,000 --> 00:01:22,520 +包括 + +51 +00:01:22,560 --> 00:01:24,160 +弹药储存设施 + +52 +00:01:24,200 --> 00:01:25,680 +航空燃料系统 + +53 +00:01:25,720 --> 00:01:27,280 +维修保障系统 + +54 +00:01:27,320 --> 00:01:29,440 +以满足固定翼舰载机 + +55 +00:01:29,480 --> 00:01:30,560 +运行需求 + +56 +00:01:30,600 --> 00:01:33,160 + + +57 +00:01:33,200 --> 00:01:35,000 +如果说出云级的改装 + +58 +00:01:35,040 --> 00:01:35,920 +让日本 + +59 +00:01:35,960 --> 00:01:38,920 +获得了运用固定翼舰载机的平台 + +60 +00:01:38,960 --> 00:01:39,560 +那么 + +61 +00:01:39,600 --> 00:01:41,040 +真正赋予这艘军舰 + +62 +00:01:41,080 --> 00:01:42,480 +航空作战能力的 + +63 +00:01:42,520 --> 00:01:44,320 +则是另一款装备 + +64 +00:01:44,360 --> 00:01:47,360 +F-35B隐身战斗机 + +65 +00:01:47,400 --> 00:01:49,080 +搭载F-35B之后 + +66 +00:01:49,120 --> 00:01:51,760 +拥有全通式飞行甲板的出云级 + +67 +00:01:51,800 --> 00:01:52,640 +便具备了 + +68 +00:01:52,680 --> 00:01:55,480 +运用固定翼隐身战斗机的可能 + +69 +00:01:55,520 --> 00:02:08,280 + + +70 +00:02:08,320 --> 00:02:10,600 +这是一架F-35B战斗机 + +71 +00:02:10,640 --> 00:02:13,480 +它是F-35闪电II战斗机家族中的 + +72 +00:02:13,520 --> 00:02:16,000 +短距起飞垂直降落型 + +73 +00:02:16,040 --> 00:02:17,880 +机长15.6米 + +74 +00:02:17,920 --> 00:02:19,560 +翼展10.7米 + +75 +00:02:19,600 --> 00:02:21,440 +机高4.36米 + +76 +00:02:21,480 --> 00:02:23,760 +空重约14.7吨 + +77 +00:02:23,800 --> 00:02:25,160 +最大起飞重量 + +78 +00:02:25,200 --> 00:02:26,440 +约27吨 + +79 +00:02:26,480 --> 00:02:27,680 +最大飞行速度 + +80 +00:02:27,720 --> 00:02:29,320 +约马赫数1.6 + +81 +00:02:29,360 --> 00:02:30,360 +作战半径 + +82 +00:02:30,400 --> 00:02:32,280 +约830公里 + +83 +00:02:32,320 --> 00:02:33,160 +当飞机 + +84 +00:02:33,200 --> 00:02:35,440 +进入垂直起降模式时 + +85 +00:02:35,480 --> 00:02:36,440 +发动机动力 + +86 +00:02:36,480 --> 00:02:37,760 +通过传动轴 + +87 +00:02:37,800 --> 00:02:39,760 +驱动升力风扇 + +88 +00:02:39,800 --> 00:02:42,200 +机腹喷口同步向下偏转 + +89 +00:02:42,240 --> 00:02:44,800 +形成前后两个升力中心 + +90 +00:02:44,840 --> 00:02:46,360 +实现垂直起飞 + +91 +00:02:46,400 --> 00:02:47,520 +垂直降落 + +92 +00:02:47,560 --> 00:02:49,440 +悬停飞行的能力 + +93 +00:02:49,480 --> 00:02:51,240 +与传统舰载机相比 + +94 +00:02:51,280 --> 00:02:52,280 +F-35B + +95 +00:02:52,320 --> 00:02:54,440 +无需弹射器和阻拦索 + +96 +00:02:54,480 --> 00:02:57,040 +即可在较小甲板上运行 + +97 +00:02:57,080 --> 00:02:58,040 +同时保留 + +98 +00:02:58,080 --> 00:02:59,840 +第五代战斗机的隐身 + +99 +00:02:59,880 --> 00:03:01,440 +和信息融合能力 + +100 +00:03:01,480 --> 00:03:02,560 + + +101 +00:03:02,600 --> 00:03:04,120 +日本军事能力的提升 + +102 +00:03:04,160 --> 00:03:06,080 +已经吸引了国际的目光 + +103 +00:03:06,120 --> 00:03:07,240 +其后续举措 + +104 +00:03:07,280 --> 00:03:08,880 +更致力于将这种实力 + +105 +00:03:08,920 --> 00:03:10,440 +延伸至海外 + +106 +00:03:10,480 --> 00:03:12,480 +无论是F-2战机 + +107 +00:03:12,520 --> 00:03:15,040 +12式能力向上型导弹 + +108 +00:03:15,080 --> 00:03:16,680 +最上级护卫舰 + +109 +00:03:16,720 --> 00:03:19,000 +还是下一代战机研发项目 + +110 +00:03:19,040 --> 00:03:19,520 +日本 + +111 +00:03:19,560 --> 00:03:20,880 +正在稳步构建 + +112 +00:03:20,920 --> 00:03:22,200 +涵盖航空 + +113 +00:03:22,240 --> 00:03:22,880 +舰船 + +114 +00:03:22,920 --> 00:03:23,400 +导弹 + +115 +00:03:23,440 --> 00:03:24,640 +与电子系统的 + +116 +00:03:24,680 --> 00:03:26,640 +自主军工产业 + +117 +00:03:26,680 --> 00:03:27,280 +然而 + +118 +00:03:27,320 --> 00:03:29,200 +对于现代军工产业来说 + +119 +00:03:29,240 --> 00:03:31,040 +仅能研发和制造武器 + +120 +00:03:31,080 --> 00:03:32,920 +并非是终极目标 + +121 +00:03:32,960 --> 00:03:34,640 +唯有进军国际市场 + +122 +00:03:34,680 --> 00:03:36,320 +参与装备的角逐 + +123 +00:03:36,360 --> 00:03:37,120 +该产业 + +124 +00:03:37,160 --> 00:03:39,040 +才能持续保持活力 + +125 +00:03:39,080 --> 00:03:39,800 +这一步 + +126 +00:03:39,840 --> 00:03:40,920 +对于战后长期 + +127 +00:03:40,960 --> 00:03:43,320 +受武器出口制约的日本而言 + +128 +00:03:43,360 --> 00:03:46,880 +在以往几乎是不可想象的 + +129 +00:03:46,920 --> 00:03:48,040 +随着日本政府 + +130 +00:03:48,080 --> 00:03:50,200 +逐步修订武器出口政策 + +131 +00:03:50,240 --> 00:03:51,400 +放松了防务装备 + +132 +00:03:51,440 --> 00:03:52,840 +对外转移的限制 + +133 +00:03:52,880 --> 00:03:53,920 +日本开始尝试 + +134 +00:03:53,960 --> 00:03:56,280 +推动本国装备走向世界 + +135 +00:03:56,320 --> 00:03:57,760 +并借助国际合作 + +136 +00:03:57,800 --> 00:03:59,440 +增强了军工产业的 + +137 +00:03:59,480 --> 00:04:01,200 +国际影响力 + +138 +00:04:01,240 --> 00:04:02,760 +这个一度被严格限制 + +139 +00:04:02,800 --> 00:04:04,040 +军力发展的国家 + +140 +00:04:04,080 --> 00:04:05,200 +正在试图寻找 + +141 +00:04:05,240 --> 00:04:06,400 +其军事工业 + +142 +00:04:06,440 --> 00:04:08,080 +在全球格局中 + +143 +00:04:08,120 --> 00:04:09,320 +扮演的角色 + +144 +00:04:09,360 --> 00:04:10,600 + + +145 +00:04:10,640 --> 00:04:11,800 +2024年 + +146 +00:04:11,840 --> 00:04:13,080 +澳大利亚海军 + +147 +00:04:13,120 --> 00:04:15,440 +启动通用护卫舰计划 + +148 +00:04:15,480 --> 00:04:18,560 +希望采购新一代水面作战舰艇 + +149 +00:04:18,600 --> 00:04:20,400 +参与竞争的名单中 + +150 +00:04:20,440 --> 00:04:21,320 +出现了一个 + +151 +00:04:21,360 --> 00:04:23,320 +过去并不常见的名字 + +152 +00:04:23,360 --> 00:04:24,520 +日本 + +153 +00:04:24,560 --> 00:04:26,240 +而日本拿出的产品 + +154 +00:04:26,280 --> 00:04:28,880 +正是最上级护卫舰 + +155 +00:04:28,920 --> 00:04:30,920 +2026年4月18日 + +156 +00:04:30,960 --> 00:04:32,120 +日本与澳大利亚 + +157 +00:04:32,160 --> 00:04:33,760 +正式签署合同 + +158 +00:04:33,800 --> 00:04:35,040 +日本向澳大利亚 + +159 +00:04:35,080 --> 00:04:36,200 +出口11艘 + +160 +00:04:36,240 --> 00:04:38,600 +升级版最上级护卫舰 + +161 +00:04:38,640 --> 00:04:39,680 +首批3艘 + +162 +00:04:39,720 --> 00:04:40,880 +由三菱重工 + +163 +00:04:40,920 --> 00:04:42,400 +在日本建造 + +164 +00:04:42,440 --> 00:04:43,440 +剩余8艘 + +165 +00:04:43,480 --> 00:04:45,440 +在澳大利亚本土建造 + +166 +00:04:45,480 --> 00:04:48,080 +首艘预计2029年交付 + +167 +00:04:48,120 --> 00:04:49,160 +总价值 + +168 +00:04:49,200 --> 00:04:52,120 +高达100亿至200亿澳元 + +169 +00:04:52,160 --> 00:04:53,800 +这是日本战后首次 + +170 +00:04:53,840 --> 00:04:55,920 +大规模出口主战装备 + +171 +00:04:55,960 --> 00:04:59,560 +也是日本军舰首次出海 + +172 +00:04:59,600 --> 00:05:49,280 + + +173 +00:05:49,320 --> 00:05:50,600 +最上级护卫舰 + +174 +00:05:50,640 --> 00:05:52,160 +是日本海上自卫队 + +175 +00:05:52,200 --> 00:05:54,360 +最新一代多用途护卫舰 + +176 +00:05:54,400 --> 00:05:56,560 +舰长约133米 + +177 +00:05:56,600 --> 00:05:58,440 +舰宽16.3米 + +178 +00:05:58,480 --> 00:05:59,600 +标准排水量 + +179 +00:05:59,640 --> 00:06:01,280 +约3900吨 + +180 +00:06:01,320 --> 00:06:02,320 +满载排水量 + +181 +00:06:02,360 --> 00:06:04,040 +约5500吨 + +182 +00:06:04,080 --> 00:06:06,440 +最高航速约30节 + +183 +00:06:06,480 --> 00:06:09,440 +续航力约5500海里 + +184 +00:06:09,480 --> 00:06:11,760 +编制舰员约90人 + +185 +00:06:11,800 --> 00:06:12,680 +动力系统 + +186 +00:06:12,720 --> 00:06:14,840 +采用柴燃联合动力系统 + +187 +00:06:14,880 --> 00:06:17,040 +总功率约7万马力 + +188 +00:06:17,080 --> 00:06:19,080 +采用双轴推进 + +189 +00:06:19,120 --> 00:06:20,040 +最上级 + +190 +00:06:20,080 --> 00:06:21,800 +大量采用隐身设计 + +191 +00:06:21,840 --> 00:06:22,920 +舰体外侧 + +192 +00:06:22,960 --> 00:06:24,960 +采用大角度倾斜结构 + +193 +00:06:25,000 --> 00:06:26,960 +降低雷达反射面积 + +194 +00:06:27,000 --> 00:06:28,360 + + +195 +00:06:28,400 --> 00:06:29,880 +一体化上层建筑 + +196 +00:06:29,920 --> 00:06:31,600 +减少雷达反射源 + +197 +00:06:31,640 --> 00:06:33,400 +提高隐身性能 + +198 +00:06:33,440 --> 00:06:34,400 +最上级 + +199 +00:06:34,440 --> 00:06:37,560 +采用OPY-2有源相控阵雷达 + +200 +00:06:37,600 --> 00:06:39,200 +属于日本国产新一代 + +201 +00:06:39,240 --> 00:06:41,040 +舰载雷达系统 + +202 +00:06:41,080 --> 00:06:42,800 +后续批次开始配备 + +203 +00:06:42,840 --> 00:06:44,880 +MK-41垂直发射系统 + +204 +00:06:44,920 --> 00:06:46,200 + + +205 +00:06:46,240 --> 00:06:46,880 +舰艏 + +206 +00:06:46,920 --> 00:06:49,080 +配备76毫米舰炮 + +207 +00:06:49,120 --> 00:06:52,120 +射速约120发每分钟 + +208 +00:06:52,160 --> 00:06:54,560 +最大射程约16公里 + +209 +00:06:54,600 --> 00:06:55,640 +舰体中部 + +210 +00:06:55,680 --> 00:06:58,320 +设置17式反舰导弹发射装置 + +211 +00:06:58,360 --> 00:07:00,640 +具备远程反舰能力 + +212 +00:07:00,680 --> 00:07:01,680 +无人化能力 + +213 +00:07:01,720 --> 00:07:04,200 +是最上级最大的特点之一 + +214 +00:07:04,240 --> 00:07:06,600 +舰艉设置大型任务舱 + +215 +00:07:06,640 --> 00:07:09,080 +能够搭载各种无人航行器 + +216 +00:07:09,120 --> 00:07:11,080 +舰艉设置单机库 + +217 +00:07:11,120 --> 00:07:12,480 +单飞行甲板 + +218 +00:07:12,520 --> 00:07:13,360 +可以搭载 + +219 +00:07:13,400 --> 00:07:16,200 +SH-60K反潜直升机一架 + +220 +00:07:16,240 --> 00:07:18,120 +以应对相关任务需求 + +221 +00:07:18,160 --> 00:07:19,960 + + +222 +00:07:20,000 --> 00:07:21,560 +2022年12月 + +223 +00:07:21,600 --> 00:07:22,200 +日本 + +224 +00:07:22,240 --> 00:07:22,880 +英国 + +225 +00:07:22,920 --> 00:07:24,680 +与意大利共同宣布 + +226 +00:07:24,720 --> 00:07:27,160 +启动全球作战空中计划 + +227 +00:07:27,200 --> 00:07:30,520 +旨在联合研制第六代隐身战斗机 + +228 +00:07:30,560 --> 00:07:31,360 +该计划 + +229 +00:07:31,400 --> 00:07:33,000 +由英国暴风项目 + +230 +00:07:33,040 --> 00:07:36,160 +与日本F-X项目整合而来 + +231 +00:07:36,200 --> 00:07:39,520 +目标在2035年前投入服役 + +232 +00:07:39,560 --> 00:07:42,000 +日本预计采购约100架 + +233 +00:07:42,040 --> 00:07:43,360 +用以替换现役的 + +234 +00:07:43,400 --> 00:07:45,800 +91架F-2战斗机 + +235 +00:07:45,840 --> 00:07:47,360 +这是日本二战后首次 + +236 +00:07:47,400 --> 00:07:48,800 +与美国之外的国家 + +237 +00:07:48,840 --> 00:07:50,560 +合作开发主战装备 + +238 +00:07:50,600 --> 00:07:51,840 + + +239 +00:07:51,880 --> 00:07:54,240 +日本持续大幅扩充军费 + +240 +00:07:54,280 --> 00:07:56,280 +放宽杀伤性武器出口 + +241 +00:07:56,320 --> 00:07:58,520 +推进部署中远程导弹 + +242 +00:07:58,560 --> 00:08:00,560 +扩充进攻性军事力量 + +243 +00:08:00,600 --> 00:08:02,480 +推动修改“和平宪法” + +244 +00:08:02,520 --> 00:08:03,720 +甚至鼓吹成为 + +245 +00:08:03,760 --> 00:08:05,200 +能战国家 + +246 +00:08:05,240 --> 00:08:07,280 +一个加速“再军事化”的日本 + +247 +00:08:07,320 --> 00:08:09,960 +正成为亚太的火药桶 + +248 +00:08:10,000 --> 00:08:13,800 + + +249 +00:08:13,840 --> 00:08:15,080 +观察日本近年来 + +250 +00:08:15,120 --> 00:08:16,400 +军事力量的发展 + +251 +00:08:16,440 --> 00:08:17,120 +其变化 + +252 +00:08:17,160 --> 00:08:19,600 +已不仅限于简单的装备更新 + +253 +00:08:19,640 --> 00:08:20,560 +更能反映出 + +254 +00:08:20,600 --> 00:08:21,640 +其安全政策 + +255 +00:08:21,680 --> 00:08:24,040 +与国家战略的深层调整 + +256 +00:08:24,080 --> 00:08:25,720 + + +257 +00:08:25,760 --> 00:08:27,120 +历史一再表明 + +258 +00:08:27,160 --> 00:08:28,120 +军备扩张 + +259 +00:08:28,160 --> 00:08:30,200 +或可带来一时的实力增强 + +260 +00:08:30,240 --> 00:08:31,400 +却难以抹平 + +261 +00:08:31,440 --> 00:08:33,680 +战争造成的伤痕 + +262 +00:08:33,720 --> 00:08:34,800 +先进的武器 + +263 +00:08:34,840 --> 00:08:36,640 +或许能改变战场形态 + +264 +00:08:36,680 --> 00:08:38,560 +却无法扭转历史的 + +265 +00:08:38,600 --> 00:08:40,560 +是非对错 + +266 +00:08:40,600 --> 00:08:43,120 +对于曾发动侵略战争的日本而言 + +267 +00:08:43,160 --> 00:08:44,760 +只有牢记历史 + +268 +00:08:44,800 --> 00:08:46,080 +珍惜和平 + +269 +00:08:46,120 --> 00:08:47,000 +才能守护 + +270 +00:08:47,040 --> 00:08:48,760 +来之不易的安宁 + +271 +00:08:48,800 --> 00:08:50,520 + + +272 +00:08:50,560 --> 00:08:51,360 +好了观众朋友们 + +273 +00:08:51,400 --> 00:08:52,480 +感谢您持续关注 + +274 +00:08:52,520 --> 00:08:54,560 +国防军事频道《军事科技》 + +275 +00:08:54,600 --> 00:08:56,480 +我们下周同一时间 + +276 +00:08:56,520 --> 00:08:56,920 +再见 + +277 +00:08:56,960 --> 00:08:57,800 + + +278 +00:08:57,840 --> 00:08:57,840 + + diff --git a/cca/data/重走战争老路的日本军备(A稿).docx b/cca/data/重走战争老路的日本军备(A稿).docx new file mode 100644 index 0000000..7072b8f Binary files /dev/null and b/cca/data/重走战争老路的日本军备(A稿).docx differ diff --git a/cca/note/CCA子项目_Brief.md b/cca/note/CCA子项目_Brief.md new file mode 100644 index 0000000..0042208 --- /dev/null +++ b/cca/note/CCA子项目_Brief.md @@ -0,0 +1,129 @@ +# CCA 唱词助手子项目 Brief + +> 主项目 → 子项目的"交接宪法":红线、技术栈、出入口接口 +> 起草日期:2026-07-04 +> 状态:主项目签发,子项目内部不修改 + +--- + +## 一、为什么做 + +**痛点**:《军事科技》每期节目剪辑完成后,编导需要制作一份唱词字幕(SRT 文件)交给责编拉到大洋系统上线。目前纯手工操作——对照 A 稿听音频逐句打字幕,费时且容易出错。 + +**升级目标**:编导只需提供 A 稿 + 粗编人声音频,系统自动走 ASR + AI 校对 + 编导审稿确认,最终输出大洋系统可直接使用的 SRT 文件。 + +**紧迫性**:切实解决当前痛点,功能不复杂,两天内出可用版本。先独立部署测试,成熟后并入 TPS 主项目。 + +--- + +## 二、做什么(功能边界) + +| 模块 | 简述 | +|---|---| +| 专有名词提取 | AI 从 A 稿中摘取军事专有名词(型号、人名、机构等),形成热词词典 | +| 讯飞 ASR 转写 | 音频 + 词典 → 带时间戳的 ASR 稿 | +| AI 校对比对 | ASR 稿 ⊕ A 稿比对,自动修正明显错误,标记存疑差异 | +| 编导审稿台 | 双屏对比 UI,差异高亮,编导点击确认/手动修改 | +| SRT 生成 | B 稿按拍词规则折行 + 时间戳 → 大洋格式 SRT | + +**具体怎么做,子项目内部讨论,本 Brief 不预设方案。** + +--- + +## 三、怎么用(目标流程) + +1. 编导剪完节目,手头有 A 稿(docx/txt)+ 粗编纯人声音频 +2. 编导上传 A 稿和音频到 CCA 系统 +3. 系统自动:提取专有名词 → 讯飞 ASR → AI 校对 → 生成初版对比 +4. 编导进入审稿台:查看差异、确认/修改 +5. 系统输出 SRT 文件 +6. 责编拿 SRT 拉到大洋系统形成唱词字幕 + +--- + +## 四、不做什么(红线) + +- ❌ **不替代编导审稿**:AI 拿不准的必须过编导确认,不全自动出 SRT +- ❌ **不改 A 稿内容**:A 稿只用于提取专有名词和提供参照,不回写 +- ❌ **不动主项目 backend 代码 / schema**(在吸收进主项目之前) +- ❌ **不复用主项目 backend/.env 的凭证**(子项目自己 .env) +- ❌ **不用讯飞大模型版 ASR**(用录音文件转写标准版,与 doco 一致) +- ❌ **不做视频处理**(输入是已分离的纯人声音频,不是视频) +- ❌ **不做内容创作**(AI 只校对不创作,尊重 ASR 底稿 + 编导意见) + +--- + +## 五、技术栈约束 + +- **运行环境**:Python 3.x + Web 前端(审稿台) +- **ASR**:讯飞开放平台 录音文件转写标准版(热词偏置注入) +- **AI/LLM**:用于专有名词提取 + 校对(具体模型子项目讨论,省 token 优先) +- **输出格式**:SRT(大洋系统兼容,有样本) +- **部署**:先部署 lanhao 配音 2.0 网站测试,后续并入 TPS +- **美术风格**:参考 `ai-labeling/example/` 目录下的设计稿(`功能区划.jpg`、`幅面参考.jpg`、`页面风格.webp`),CCA 的 UI 风格与 TPS 主项目保持一致 + +--- + +## 六、交付什么(出口接口) + +### 6.1 并入架构(同一服务器、同一进程) + +CCA 最终**不是独立微服务**,而是代码合并进 TPS 同一套服务: + +- **后端**:CCA 的 API 路由并入 `backend/app/api/`(如 `cca.py`),业务逻辑并入 `backend/app/services/`(如 `cca_service.py`),共用同一个 FastAPI 进程 +- **前端**:CCA 页面并入 `frontend/src/pages/`(如 `CCA/` 目录),作为 TPS React 应用的一个路由页面(`/cca`) +- **同一台服务器**:不存在跨服务调用,共用 TPS 的 PostgreSQL、同一个 `.env` + +### 6.2 开发阶段的独立形态 + +并入前的开发测试阶段,CCA 以独立可运行的 Web 应用存在: +- 独立的后端(FastAPI 或轻量框架)+ 前端(审稿台 UI) +- 可单独部署到 lanhao 配音 2.0 网站跑通验证 +- 代码结构从一开始就按"能干净并入 TPS"设计(目录命名、API 风格、前端组件规范对齐主项目) + +### 6.3 具体交付清单 + +| 交付物 | 说明 | +|---|---| +| CCA 后端 API | 文件上传(A稿+音频)、ASR 任务触发/轮询、校对结果、审稿确认、SRT 下载 | +| 讯飞 ASR 适配层 | 热词注入 + 转写 + 解析,可被主项目其他模块复用(与 doco 逻辑同源) | +| 专有名词提取服务 | AI 从 A 稿提取军事专名 → 热词词典 | +| AI 校对比对服务 | ASR 稿 ⊕ A 稿差异标记(自动修正 + 存疑清单) | +| 编导审稿台前端 | 双屏对比 UI + 差异高亮 + 确认/手改交互 | +| 拍词折行引擎 | 按规则把 B 稿折行 + 结合时间戳生成 SRT | +| SRT 输出 | 大洋系统兼容格式(有样本对标) | + +### 6.4 配置与凭证 +- 开发阶段:cca 自己的 `.env`(讯飞 Key + LLM Key) +- 并入后:凭证合并进 TPS 主项目 `backend/.env`,讯飞 Key 可与 doco 共用 +- 主项目 `docs/api_credentials_inventory.md` 登记 CCA 凭证元信息 + +### 6.5 不接受 +- 并入前,子项目自己改主项目 backend 代码、schema、迁移 +- 未经主项目审批引入主项目没有的技术栈 +- 并入时引入与主项目冲突的依赖版本 + +--- + +## 七、入口接口(子项目要知道的主项目现状) + +- **主项目已有讯飞 ASR 经验**:doco 子项目已跑通讯飞录音文件转写标准版,签名/上传/轮询/解析全套逻辑可复用 +- **主项目有 `api_credentials_inventory.md`**:凭证元信息登记表 +- **主项目有跨子项目协作规则**:PRD 版本管理等,见 `跨子项目协作规则.md` + +--- + +## 八、制片人待提供 + +- [ ] 拍词规则(责编拍词的具体 markdown 规则文档) +- [ ] 大洋 SRT 样本文件(一份能用的真实样本) +- [ ] 粗编音频样本(一期的真实音频,用于开发测试) +- [ ] A 稿样本(对应的编导 A 稿) + +--- + +## 九、本 Brief 自身的修订规则 + +- 本 Brief 不在子项目内修改 +- 红线/技术栈如有变更,**主项目这边发新版** +- 子项目可在自己的 chat 里建议调整,调整动作只能在主项目发生 diff --git a/cca/requirements.txt b/cca/requirements.txt new file mode 100644 index 0000000..08c226b --- /dev/null +++ b/cca/requirements.txt @@ -0,0 +1,5 @@ +requests>=2.28 +python-dotenv>=1.0 +mutagen>=1.47 +openai>=1.0 +python-docx>=1.0 diff --git a/cca/src/ai_line_breaker.py b/cca/src/ai_line_breaker.py new file mode 100644 index 0000000..ae5ad05 --- /dev/null +++ b/cca/src/ai_line_breaker.py @@ -0,0 +1,224 @@ +# -*- coding: utf-8 -*- +""" +AI 折行引擎 — 用 DeepSeek 对 ASR 长句做语义折行 + +对于 ≤14 字的句子直接输出,>14 字的句子批量发给 AI 折行。 +""" + +import json +import os +import sys +from pathlib import Path +from typing import List, Tuple + +try: + from dotenv import load_dotenv + _env_path = Path(__file__).resolve().parent.parent / ".env" + if _env_path.exists(): + load_dotenv(str(_env_path), override=True) +except Exception: + pass + +from openai import OpenAI + +DEEPSEEK_API_KEY = os.environ.get("DEEPSEEK_API_KEY", "").strip() +DEEPSEEK_BASE_URL = os.environ.get("DEEPSEEK_BASE_URL", "https://api.deepseek.com").strip() +DEEPSEEK_MODEL = os.environ.get("DEEPSEEK_MODEL", "deepseek-chat").strip() + +MAX_CHARS = 14 +MAX_CHARS_SOFT = 16 +SILENCE_THRESHOLD_MS = 2000 + +SYSTEM_PROMPT = """你是电视节目唱词字幕的折行助手。你的任务是将一段文字按照以下规则折成多行: + +规则: +1. 每行最多14个字(中文字符、英文字母、数字各算1个字) +2. 去掉逗号、句号、感叹号、问号、顿号、分号、冒号、省略号等标点,只保留引号(""''「」)和书名号(《》) +3. 折行要符合语义和阅读习惯,不能把词语切断 +4. 每行不一定要凑满14字,可以是5字、8字、10字等,关键是语义完整 +5. 保持原文内容不变,不增不减不改字 + +输出格式:每行一句,不加序号,不加标点(引号和书名号除外)。""" + +USER_PROMPT_TEMPLATE = """请将以下文字折行(每行≤14字,去标点保引号,按语义断句): + +{text}""" + +BATCH_USER_PROMPT = """请将以下编号文字逐条折行(每行≤14字,去标点保引号,按语义断句)。 +每条之间用空行分隔,保持编号对应。 + +{numbered_texts}""" + + +def _create_client() -> OpenAI: + if not DEEPSEEK_API_KEY: + raise ValueError("请在 .env 中设置 DEEPSEEK_API_KEY") + return OpenAI(api_key=DEEPSEEK_API_KEY, base_url=DEEPSEEK_BASE_URL) + + +def ai_break_single(text: str, client: OpenAI) -> List[str]: + """单句 AI 折行""" + resp = client.chat.completions.create( + model=DEEPSEEK_MODEL, + messages=[ + {"role": "system", "content": SYSTEM_PROMPT}, + {"role": "user", "content": USER_PROMPT_TEMPLATE.format(text=text)}, + ], + temperature=0.1, + max_tokens=500, + ) + result = resp.choices[0].message.content.strip() + lines = [l.strip() for l in result.split("\n") if l.strip()] + return lines + + +def ai_break_batch(texts: List[str], client: OpenAI) -> List[List[str]]: + """ + 批量 AI 折行(减少 API 调用次数) + 每批最多 20 条,避免输出过长出错 + """ + if not texts: + return [] + + numbered = "\n".join(f"[{i+1}] {t}" for i, t in enumerate(texts)) + resp = client.chat.completions.create( + model=DEEPSEEK_MODEL, + messages=[ + {"role": "system", "content": SYSTEM_PROMPT}, + {"role": "user", "content": BATCH_USER_PROMPT.format(numbered_texts=numbered)}, + ], + temperature=0.1, + max_tokens=3000, + ) + result = resp.choices[0].message.content.strip() + + # 解析结果:按空行或编号分隔 + all_results = [] + current_lines = [] + + for line in result.split("\n"): + line = line.strip() + # 检测新编号开头 [N] 或纯空行作为分隔 + if not line: + if current_lines: + all_results.append(current_lines) + current_lines = [] + continue + + # 去掉可能的编号前缀 + import re + cleaned = re.sub(r'^\[\d+\]\s*', '', line) + if cleaned: + current_lines.append(cleaned) + + if current_lines: + all_results.append(current_lines) + + # 如果解析结果数量不匹配,回退到逐条处理 + if len(all_results) != len(texts): + print(f"[AI折行] 批量解析不匹配 (期望{len(texts)}条,得到{len(all_results)}条),回退逐条处理") + all_results = [] + for text in texts: + lines = ai_break_single(text, client) + all_results.append(lines) + + return all_results + + +def process_sentences_with_ai( + sentences: List[Tuple[int, int, str, int]], + batch_size: int = 15, +) -> List[Tuple[int, int, str]]: + """ + 用 AI 折行处理 ASR 句子列表。 + + 输入: [(start_ms, end_ms, text, speaker_id), ...] + 输出: [(start_ms, end_ms, text), ...] + + 策略: + - ≤14 字:直接输出(去标点) + - >14 字:批量调 AI 折行 + - 句间 >2秒:插入空白行 + """ + from line_breaker import clean_punctuation + + if not sentences: + return [] + + client = _create_client() + result = [] + + # 先收集需要 AI 折行的句子索引 + needs_ai = [] # (original_index, text) + for i, (bg, ed, text, spk) in enumerate(sentences): + cleaned = clean_punctuation(text) + if len(cleaned) > MAX_CHARS: + needs_ai.append((i, cleaned)) + + # 批量调 AI + ai_results = {} # index -> [lines] + if needs_ai: + print(f"[AI折行] 共 {len(needs_ai)} 句需要 AI 折行...") + for batch_start in range(0, len(needs_ai), batch_size): + batch = needs_ai[batch_start:batch_start + batch_size] + batch_texts = [t for _, t in batch] + batch_indices = [idx for idx, _ in batch] + + print(f"[AI折行] 处理第 {batch_start+1}-{batch_start+len(batch)} 条...") + try: + broken = ai_break_batch(batch_texts, client) + for idx, lines in zip(batch_indices, broken): + ai_results[idx] = lines + except Exception as e: + print(f"[AI折行] 批量失败: {e},回退逐条处理") + for idx, text in batch: + try: + lines = ai_break_single(text, client) + ai_results[idx] = lines + except Exception as e2: + print(f"[AI折行] 第{idx}句失败: {e2},使用机械切分") + from line_breaker import break_sentence + ai_results[idx] = break_sentence(text) + + # 组装最终结果 + for i, (bg, ed, text, spk) in enumerate(sentences): + # 检查空白 + if i > 0: + prev_ed = sentences[i - 1][1] + gap = bg - prev_ed + if gap > SILENCE_THRESHOLD_MS: + result.append((prev_ed, bg, "")) + + cleaned = clean_punctuation(text) + if not cleaned.strip(): + continue + + if i in ai_results: + lines = ai_results[i] + else: + lines = [cleaned] + + # 后处理:AI 偶尔返回超长行,强制二次切分 + from line_breaker import break_sentence + final_lines = [] + for line in lines: + if len(line) > MAX_CHARS_SOFT: + final_lines.extend(break_sentence(line)) + else: + final_lines.append(line) + lines = final_lines + + # 为子行分配时间戳 + total_chars = sum(len(l) for l in lines) + duration = ed - bg + current_ms = bg + + for line in lines: + if not line.strip(): + continue + line_duration = int(duration * len(line) / total_chars) if total_chars > 0 else 0 + line_end = min(current_ms + line_duration, ed) + result.append((current_ms, line_end, line)) + current_ms = line_end + + return result diff --git a/cca/src/ai_proofreader.py b/cca/src/ai_proofreader.py new file mode 100644 index 0000000..de8b6e0 --- /dev/null +++ b/cca/src/ai_proofreader.py @@ -0,0 +1,163 @@ +# -*- coding: utf-8 -*- +""" +AI 校对器 — ASR 稿与 A 稿比对 + 上下文纠错 + +解决的核心问题: +- ASR 同音字误识别("建制"→"舰只"、"舰手"→"舰艏") +- 军事术语规范化("f15j"→"F-15J") +- 的/地/得纠错 +- 去除口语填充词("嗯""那个""就是说") + +策略: +- 将 ASR 全文 + A 稿全文一起发给 DeepSeek +- AI 结合节目主题和上下文做纠错 +- 返回修正后的句子列表 + 修改说明 +""" + +import json +import os +import sys +from pathlib import Path +from typing import List, Tuple, Dict + +try: + from dotenv import load_dotenv + _env_path = Path(__file__).resolve().parent.parent / ".env" + if _env_path.exists(): + load_dotenv(str(_env_path), override=True) +except Exception: + pass + + +PROOFREAD_SYSTEM_PROMPT = """你是电视军事节目《军事科技》的字幕校对专家。你将收到两份材料: +1. **ASR稿**:语音识别的转写结果,带有时间编号,是字幕的基础 +2. **A稿**:编导写的节目文稿(仅包含解说词,不包含专家采访的具体内容) + +你的任务是校对 ASR 稿中的**语音识别错误**。 + +**铁律(违反任何一条都算失败):** +- ASR稿是已经录好的音频的转写,内容不能改——**绝不润色语句、绝不调整语序、绝不增删实词** +- 只修三类问题:① 错别字/同音字 ② 术语格式 ③ 口语填充词 +- 除这三类外的一切文字,原封不动照抄,一个字都不能动 +- A稿只用来判断"这个词在本期节目的语境下应该是哪个字",不能把ASR稿往A稿的措辞上靠 + +**允许修的三类:** +1. **同音字/错别字**(ASR听错的字):如"建制"→"舰只"、"舰手"→"舰艏"、"继承"→"击沉"、"空花弹"→"滑翔弹" +2. **术语格式**:英文型号大小写+连字符("f15j"→"F-15J"、"v22"→"V-22"、"rq四"→"RQ-4") +3. **口语填充词删除**:只删"嗯""呃""唉""啊""呢""那个""就是说""这个"这类纯填充词。如果"这个"后面紧跟名词作指示代词("这个导弹"),保留不删 + +**绝对不许做的(哪怕你觉得改了更好也不许):** +- 不许调整语序("它在性质上就是"不许改成"它本质上就是") +- 不许替换实词("不是那么特别的顺利"不许改成"不太顺利") +- 不许增删标点来改变句子结构 +- 不许把口语化表达改成书面语 +- 不许根据A稿的措辞替换ASR中意思相同但用词不同的表达 + +**输出格式:** +JSON数组,每个元素:{"id": 编号, "original": "原文", "corrected": "修正后", "changes": "修改说明(无修改写空字符串)"} +只输出JSON,不要其他内容。""" + + +PROOFREAD_USER_TEMPLATE = """**A稿(节目文稿,仅供参考):** +{script_text} + +**ASR稿(需要校对,请逐条检查):** +{asr_text}""" + + +def _create_client(): + api_key = os.environ.get("DEEPSEEK_API_KEY", "").strip() + if not api_key: + raise ValueError("请在 .env 中设置 DEEPSEEK_API_KEY") + from openai import OpenAI + return OpenAI( + api_key=api_key, + base_url=os.environ.get("DEEPSEEK_BASE_URL", "https://api.deepseek.com"), + ) + + +def proofread_batch( + asr_sentences: List[Tuple[int, int, str, int]], + script_text: str, + batch_size: int = 30, +) -> List[Tuple[int, int, str, int]]: + """ + 对 ASR 句子列表做 AI 校对。 + + 输入: + asr_sentences: [(start_ms, end_ms, text, speaker_id), ...] + script_text: A稿全文 + batch_size: 每批处理的句子数 + + 返回: + 校对后的句子列表,格式同输入 + """ + if not asr_sentences: + return [] + + client = _create_client() + + # A稿截取(太长的话截前8000字,够提供上下文了) + script_truncated = script_text[:8000] if len(script_text) > 8000 else script_text + + corrected_sentences = list(asr_sentences) # 浅拷贝 + total_changes = 0 + + for batch_start in range(0, len(asr_sentences), batch_size): + batch = asr_sentences[batch_start:batch_start + batch_size] + batch_end = batch_start + len(batch) + + # 构建 ASR 文本(带编号) + asr_lines = [] + for i, (bg, ed, text, spk) in enumerate(batch): + asr_lines.append(f"[{i+1}] {text}") + asr_text = "\n".join(asr_lines) + + print(f"[校对] 处理第 {batch_start+1}-{batch_end} 句...") + + try: + resp = client.chat.completions.create( + model=os.environ.get("DEEPSEEK_MODEL", "deepseek-chat"), + messages=[ + {"role": "system", "content": PROOFREAD_SYSTEM_PROMPT}, + {"role": "user", "content": PROOFREAD_USER_TEMPLATE.format( + script_text=script_truncated, + asr_text=asr_text, + )}, + ], + temperature=0.1, + max_tokens=4000, + ) + + result_text = resp.choices[0].message.content.strip() + + # 尝试解析 JSON + # 去掉可能的 markdown 代码块标记 + if result_text.startswith("```"): + result_text = result_text.split("\n", 1)[1] + if result_text.endswith("```"): + result_text = result_text[:-3] + result_text = result_text.strip() + + corrections = json.loads(result_text) + + # 应用修正 + for item in corrections: + idx = item.get("id", 0) - 1 # 编号从1开始 + corrected = item.get("corrected", "") + changes = item.get("changes", "") + + if 0 <= idx < len(batch) and corrected and changes: + original_idx = batch_start + idx + bg, ed, _, spk = corrected_sentences[original_idx] + corrected_sentences[original_idx] = (bg, ed, corrected, spk) + total_changes += 1 + print(f" 修正: '{item.get('original','')}' → '{corrected}' ({changes})") + + except json.JSONDecodeError as e: + print(f"[校对] JSON解析失败,跳过本批: {e}", file=sys.stderr) + except Exception as e: + print(f"[校对] 出错: {e}", file=sys.stderr) + + print(f"[校对] 完成,共修正 {total_changes} 处") + return corrected_sentences diff --git a/cca/src/asr_client.py b/cca/src/asr_client.py new file mode 100644 index 0000000..b76c07d --- /dev/null +++ b/cca/src/asr_client.py @@ -0,0 +1,229 @@ +# -*- coding: utf-8 -*- +""" +讯飞 ASR 客户端 — 适配自 doco/src/doco/asr_adapter.py +录音文件转写标准版: https://raasr.xfyun.cn/v2/api +""" + +import base64 +import hashlib +import hmac +import json +import os +import sys +import time +import wave +from pathlib import Path +from urllib.parse import quote +from typing import List, Tuple, Optional + +import requests + +# ======================================================================== +# 凭证 +# ======================================================================== + +try: + from dotenv import load_dotenv + _env_path = Path(__file__).resolve().parent.parent / ".env" + if _env_path.exists(): + load_dotenv(str(_env_path), override=True) +except Exception: + pass + +APP_ID = os.environ.get("XFYUN_APP_ID", "").strip() +SECRET_KEY = os.environ.get("XFYUN_SECRET_KEY", "").strip() + +# ======================================================================== +# 接口配置 +# ======================================================================== + +HOST = "https://raasr.xfyun.cn/v2/api" +UPLOAD_URL = HOST + "/upload" +RESULT_URL = HOST + "/getResult" + +LANGUAGE = "cn" +PD = "mil" +ENG_SMOOTHPROC = "true" +ENG_COLLOQPROC = "true" +ROLE_TYPE = "1" +ROLE_NUM = "0" + +POLL_INTERVAL_SECONDS = 30 +MAX_WAIT_MINUTES = 30 + + +# ======================================================================== +# 签名 +# ======================================================================== + +def _make_signa(app_id: str, secret_key: str, ts: str) -> str: + base_string = (app_id + ts).encode("utf-8") + md5_str = hashlib.md5(base_string).hexdigest() + mac = hmac.new( + secret_key.encode("utf-8"), + md5_str.encode("utf-8"), + digestmod=hashlib.sha1, + ) + return base64.b64encode(mac.digest()).decode("utf-8") + + +def _get_audio_duration_ms(filepath: str) -> int: + ext = os.path.splitext(filepath)[1].lower() + if ext == ".wav": + with wave.open(filepath, "rb") as wf: + return int(round(wf.getnframes() / wf.getframerate() * 1000)) + if ext == ".mp3": + try: + from mutagen.mp3 import MP3 + return int(MP3(filepath).info.length * 1000) + except ImportError: + print("[警告] 需要 mutagen 库来读取 MP3 时长: pip install mutagen", file=sys.stderr) + return 0 + raise ValueError(f"不支持的音频格式: {ext}") + + +# ======================================================================== +# 上传 +# ======================================================================== + +def upload_audio(filepath: str, hot_words: Optional[List[str]] = None) -> str: + if not APP_ID or not SECRET_KEY: + raise ValueError("请先在 .env 中设置 XFYUN_APP_ID 和 XFYUN_SECRET_KEY") + + file_size = os.path.getsize(filepath) + file_name = os.path.basename(filepath) + duration_ms = _get_audio_duration_ms(filepath) + ts = str(int(time.time())) + signa = _make_signa(APP_ID, SECRET_KEY, ts) + + params = { + "appId": APP_ID, + "signa": signa, + "ts": ts, + "fileSize": str(file_size), + "fileName": file_name, + "duration": str(duration_ms), + "language": LANGUAGE, + "pd": PD, + "eng_smoothproc": ENG_SMOOTHPROC, + "eng_colloqproc": ENG_COLLOQPROC, + "roleType": ROLE_TYPE, + "roleNum": ROLE_NUM, + } + + if hot_words: + params["hotWord"] = "|".join(hot_words[:200]) + + url_parts = [f"{quote(k, safe='')}={quote(str(v), safe='')}" for k, v in params.items()] + url = f"{UPLOAD_URL}?{'&'.join(url_parts)}" + + with open(filepath, "rb") as f: + audio_bytes = f.read() + + print(f"[ASR] 上传音频: {file_name} ({file_size/1024/1024:.1f}MB)") + resp = requests.post(url, headers={"Content-Type": "application/json"}, data=audio_bytes, timeout=300) + data = resp.json() + + if data.get("code") != "000000": + raise RuntimeError(f"上传失败: code={data.get('code')}, desc={data.get('descInfo')}") + + order_id = data["content"]["orderId"] + print(f"[ASR] 上传成功, orderId={order_id}") + return order_id + + +# ======================================================================== +# 轮询 +# ======================================================================== + +def poll_until_done(order_id: str) -> dict: + start_time = time.time() + print(f"[ASR] 开始轮询 (每{POLL_INTERVAL_SECONDS}秒)...") + while True: + elapsed = time.time() - start_time + if elapsed > MAX_WAIT_MINUTES * 60: + raise TimeoutError(f"超过 {MAX_WAIT_MINUTES} 分钟未完成") + + ts = str(int(time.time())) + signa = _make_signa(APP_ID, SECRET_KEY, ts) + params = { + "appId": APP_ID, + "signa": signa, + "ts": ts, + "orderId": order_id, + "resultType": "transfer", + } + url_parts = [f"{quote(k, safe='')}={quote(str(v), safe='')}" for k, v in params.items()] + url = f"{RESULT_URL}?{'&'.join(url_parts)}" + + resp = requests.post(url, timeout=30) + data = resp.json() + order_info = data.get("content", {}).get("orderInfo", {}) + status = order_info.get("status") + + if status == 4: + print(f"[ASR] 转写完成 (耗时{int(elapsed)}秒)") + return data + if status == -1: + raise RuntimeError(f"转写失败: {data}") + + print(f"[ASR] 等待中... ({int(elapsed)}秒)") + time.sleep(POLL_INTERVAL_SECONDS) + + +# ======================================================================== +# 解析 +# ======================================================================== + +def parse_result(order_result_str: str) -> List[Tuple[int, int, str, int]]: + """ + 解析讯飞返回结果 + 返回 [(start_ms, end_ms, text, speaker_id), ...] + """ + if not order_result_str: + return [] + + cleaned = order_result_str.replace("\\\\", "\\") + outer = json.loads(cleaned) + + sentences = [] + for item in outer.get("lattice", []): + inner_str = item.get("json_1best", "") + if not inner_str: + continue + inner = json.loads(inner_str) + st = inner.get("st", {}) + bg = int(st.get("bg", 0)) + ed = int(st.get("ed", 0)) + rl = int(st.get("rl", 0)) + + words = [] + for rt in st.get("rt", []): + for ws in rt.get("ws", []): + for cw in ws.get("cw", []): + w = cw.get("w", "").strip() + wp = cw.get("wp", "n") + if w and wp != "g": + words.append(w) + sentence = "".join(words).strip() + if sentence: + sentences.append((bg, ed, sentence, rl)) + + return sentences + + +# ======================================================================== +# 完整流程 +# ======================================================================== + +def transcribe(audio_path: str, hot_words: Optional[List[str]] = None) -> Tuple[List[Tuple[int, int, str, int]], str]: + """ + 完整转写: 上传 → 轮询 → 解析 + 返回 (sentences, raw_json_str) + sentences: [(start_ms, end_ms, text, speaker_id), ...] + """ + order_id = upload_audio(audio_path, hot_words=hot_words) + result_data = poll_until_done(order_id) + order_result_str = result_data["content"]["orderResult"] + sentences = parse_result(order_result_str) + return sentences, order_result_str diff --git a/cca/src/hotword_extractor.py b/cca/src/hotword_extractor.py new file mode 100644 index 0000000..bc35ea4 --- /dev/null +++ b/cca/src/hotword_extractor.py @@ -0,0 +1,210 @@ +# -*- coding: utf-8 -*- +""" +热词提取器 — 从 A 稿中提取军事专有名词,注入讯飞 ASR 热词 + +两种模式: +1. 规则提取(不消耗 API): 匹配 A 稿中的武器型号、专有名词等 +2. AI 提取(消耗 DeepSeek API): 让 AI 理解全文后提取专业术语 + +热词用途: 注入讯飞 ASR 的 hotWord 参数,提升领域识别准确率 +讯飞限制: 最多 200 个热词,每个 2-16 字,用 | 分隔 +""" + +import os +import re +import sys +from pathlib import Path +from typing import List, Optional + +# ======================================================================== +# 规则提取 +# ======================================================================== + +# 常见军事装备型号模式 +MILITARY_PATTERNS = [ + # 武器型号: F-35B, F-15J, RQ-4, V-22 等 + re.compile(r'[A-Z]{1,3}-?\d{1,4}[A-Z]?(?:/[A-Z])?'), + # 中文+数字型号: 12式, 25式, 17式 + re.compile(r'\d{1,3}式'), + # 导弹/武器名称中的英文缩写 + re.compile(r'(?:MK|ESSM|LM|OPY|FCS)-?\d*[A-Z]*'), +] + +# 军事领域高频词(手动维护,补充 ASR 容易错的同音词) +MILITARY_VOCAB = [ + # 海军 + "舰只", "舰艇", "舰载机", "护卫舰", "驱逐舰", "航空母舰", "航母", + "出云级", "出云号", "日向级", "日向号", "加贺号", "最上级", + "伊势号", "满载排水量", "飞行甲板", "舰艏", "舰艉", "舰宽", + "垂直发射系统", "近防系统", "反潜", "扫雷", + # 空军 + "战斗机", "隐身战斗机", "舰载机", "无人机", "旋翼机", + "航空自卫队", "航空宇宙自卫队", + # 陆军/导弹 + "巡航导弹", "反舰导弹", "高超音速", "滑翔弹", + "战斧", "陆上自卫队", "海上自卫队", + "岸基", "弹径", "弹体", "射程", "马赫数", + # 通用军事 + "防卫省", "自卫队", "专守防卫", "和平宪法", + "军备", "军售", "军费", "军工", "军舰", + "进攻性", "防御性", "远程打击", "精确打击", + "作战编队", "态势感知", "火力演习", + # 人名/地名 + "蓝皓", "熊本县", "南鸟岛", "东富士", + # 节目相关 + "军事科技", "国防军事频道", +] + + +def extract_by_rules(text: str) -> List[str]: + """用正则从文本中提取军事术语""" + found = set() + + # 正则匹配 + for pattern in MILITARY_PATTERNS: + for match in pattern.finditer(text): + word = match.group().strip() + if 2 <= len(word) <= 16: + found.add(word) + + # 固定词表匹配(只加文本中确实出现的词) + for word in MILITARY_VOCAB: + if word in text: + found.add(word) + + return sorted(found) + + +# ======================================================================== +# AI 提取 +# ======================================================================== + +AI_EXTRACT_PROMPT = """你是军事节目的专有名词提取助手。请从以下节目文稿中提取所有军事专有名词和术语。 + +提取范围: +1. 武器装备型号(如 F-35B、12式反舰导弹、战斧巡航导弹) +2. 军事单位/部队名称(如 航空自卫队、陆上自卫队) +3. 军舰/飞机名称(如 出云号、日向级) +4. 军事术语(如 垂直发射系统、高超音速滑翔弹、专守防卫) +5. 人名、地名(如 蓝皓、熊本县、南鸟岛) +6. 容易被语音识别混淆的词(如 "舰只"容易被识别为"建制","舰艏"容易被识别为"舰手") + +输出格式:每行一个词,不加序号,不加解释。每个词 2-16 字。""" + + +def extract_by_ai(text: str) -> List[str]: + """用 DeepSeek 从文本中提取专有名词""" + try: + from dotenv import load_dotenv + _env_path = Path(__file__).resolve().parent.parent / ".env" + if _env_path.exists(): + load_dotenv(str(_env_path), override=True) + except Exception: + pass + + api_key = os.environ.get("DEEPSEEK_API_KEY", "").strip() + if not api_key: + print("[热词] DeepSeek 未配置,跳过 AI 提取", file=sys.stderr) + return [] + + from openai import OpenAI + client = OpenAI( + api_key=api_key, + base_url=os.environ.get("DEEPSEEK_BASE_URL", "https://api.deepseek.com"), + ) + + # 文稿太长时截取前6000字 + truncated = text[:6000] if len(text) > 6000 else text + + resp = client.chat.completions.create( + model=os.environ.get("DEEPSEEK_MODEL", "deepseek-chat"), + messages=[ + {"role": "system", "content": AI_EXTRACT_PROMPT}, + {"role": "user", "content": truncated}, + ], + temperature=0.1, + max_tokens=2000, + ) + + result = resp.choices[0].message.content.strip() + words = [] + for line in result.split("\n"): + word = line.strip().strip("-").strip("·").strip("•").strip() + if word and 2 <= len(word) <= 16: + words.append(word) + + return words + + +# ======================================================================== +# 读取 A 稿 +# ======================================================================== + +def read_docx_text(docx_path: str) -> str: + """从 docx 文件中提取纯文本""" + try: + from docx import Document + doc = Document(docx_path) + return "\n".join(p.text for p in doc.paragraphs if p.text.strip()) + except ImportError: + print("[热词] 需要 python-docx 库: pip install python-docx", file=sys.stderr) + return "" + + +def read_text_file(path: str) -> str: + """读取 txt 文件""" + with open(path, "r", encoding="utf-8") as f: + return f.read() + + +# ======================================================================== +# 主入口 +# ======================================================================== + +def extract_hotwords( + script_path: str, + use_ai: bool = True, + max_words: int = 200, +) -> List[str]: + """ + 从 A 稿提取热词列表 + + script_path: A 稿路径 (.docx 或 .txt) + use_ai: 是否使用 AI 提取(默认 True) + max_words: 最大热词数(讯飞限制 200) + """ + ext = os.path.splitext(script_path)[1].lower() + if ext == ".docx": + text = read_docx_text(script_path) + elif ext in (".txt", ".md"): + text = read_text_file(script_path) + else: + print(f"[热词] 不支持的文件格式: {ext}", file=sys.stderr) + return [] + + if not text: + return [] + + # 规则提取(免费) + rule_words = extract_by_rules(text) + print(f"[热词] 规则提取: {len(rule_words)} 个") + + # AI 提取(可选) + ai_words = [] + if use_ai: + print("[热词] AI 提取中...") + ai_words = extract_by_ai(text) + print(f"[热词] AI 提取: {len(ai_words)} 个") + + # 合并去重 + seen = set() + merged = [] + for word in ai_words + rule_words: # AI 结果优先 + if word not in seen: + seen.add(word) + merged.append(word) + + # 截取前 max_words 个 + result = merged[:max_words] + print(f"[热词] 最终热词: {len(result)} 个") + return result diff --git a/cca/src/line_breaker.py b/cca/src/line_breaker.py new file mode 100644 index 0000000..1515d2b --- /dev/null +++ b/cca/src/line_breaker.py @@ -0,0 +1,156 @@ +# -*- coding: utf-8 -*- +""" +折行引擎 — 将 ASR 句子按拍词规则折成 ≤14 字/行的字幕行 + +规则: +A. 每行 ≤ 14 字 +B. ASR 中 >2 秒空白 → 插入空白行 +C. 按语义断句(不机械凑满 14 字) +D. 去掉逗号/句号/感叹号/问号等标点,只保留引号 +""" + +import re +from typing import List, Tuple + +MAX_CHARS_PER_LINE = 14 +MAX_CHARS_SOFT = 16 # 找不到好断点时允许的最大宽容值 +SILENCE_THRESHOLD_MS = 2000 # >2秒空白插入空行 + +# 保留的标点(引号类) +KEEP_PUNCTUATION = set('""''「」『』《》') + +# 需要去掉的标点 +REMOVE_PUNCTUATION = re.compile(r'[,。!?、;:…—·\,\.\!\?\;\:]') + +# 语义断句的优先切分点(按优先级排序) +BREAK_PATTERNS = [ + re.compile(r'(?<=[。!?])'), + re.compile(r'(?<=[,、;:])'), + re.compile(r'(?<=》)'), + re.compile('(?<=[”’』」])'), # 右引号后: " ' 』 」 +] + + +def clean_punctuation(text: str) -> str: + """去掉标点,保留引号类""" + result = [] + for ch in text: + if ch in KEEP_PUNCTUATION: + result.append(ch) + elif REMOVE_PUNCTUATION.match(ch): + continue + else: + result.append(ch) + return "".join(result) + + +def break_sentence(text: str) -> List[str]: + """ + 将一个句子按语义折行,每行 ≤ MAX_CHARS_PER_LINE 字。 + 先尝试在自然断句点切分,如果不行就硬切。 + """ + if len(text) <= MAX_CHARS_PER_LINE: + return [text] if text.strip() else [] + + # 14-16字且找不到好断点时,允许不切(人工拍词也偶尔允许略超) + if len(text) <= MAX_CHARS_SOFT: + # 只有在有明显语义断点时才切 + for pattern in BREAK_PATTERNS: + matches = list(pattern.finditer(text)) + if matches: + pos = matches[-1].end() + if 3 <= pos <= len(text) - 3: + return [text[:pos].strip(), text[pos:].strip()] + return [text] + + lines = [] + remaining = text + + while len(remaining) > MAX_CHARS_PER_LINE: + # 在前14字范围内找最佳切分点(从后往前找) + best_pos = -1 + window = remaining[:MAX_CHARS_PER_LINE] + + # 尝试在语义点切分 + for pattern in BREAK_PATTERNS: + matches = list(pattern.finditer(window)) + if matches: + pos = matches[-1].end() + if 3 <= pos <= MAX_CHARS_PER_LINE: + best_pos = pos + break + + if best_pos == -1: + # 没有好的语义切分点,尝试在常见虚词前切 + for i in range(min(MAX_CHARS_PER_LINE, len(remaining)) - 1, 2, -1): + ch = remaining[i] + if ch in "的了是在和与而但又或则也还却并且从向把被让给": + best_pos = i + break + + if best_pos == -1: + # 实在找不到,硬切在14字 + best_pos = MAX_CHARS_PER_LINE + + line = remaining[:best_pos].strip() + if line: + lines.append(line) + remaining = remaining[best_pos:].strip() + + if remaining.strip(): + lines.append(remaining.strip()) + + return lines + + +def process_sentences( + sentences: List[Tuple[int, int, str, int]], +) -> List[Tuple[int, int, str]]: + """ + 将 ASR 句子列表处理为折行后的字幕行列表。 + + 输入: [(start_ms, end_ms, text, speaker_id), ...] + 输出: [(start_ms, end_ms, text), ...] 其中 text="" 表示空白行 + + 处理逻辑: + 1. 检测句子间空白 >2秒 → 插入空白行 + 2. 清理标点 + 3. 按规则折行 + 4. 为折行后的子行分配时间戳(按字数比例) + """ + if not sentences: + return [] + + result = [] + + for i, (bg, ed, text, _spk) in enumerate(sentences): + # 检查与前一句的空白 + if i > 0: + prev_ed = sentences[i - 1][1] + gap = bg - prev_ed + if gap > SILENCE_THRESHOLD_MS: + # 插入空白行,占据空白时段 + result.append((prev_ed, bg, "")) + + # 清理标点 + cleaned = clean_punctuation(text) + if not cleaned.strip(): + continue + + # 折行 + lines = break_sentence(cleaned) + if not lines: + continue + + # 为每个子行按字数比例分配时间戳 + total_chars = sum(len(l) for l in lines) + duration = ed - bg + current_ms = bg + + for line in lines: + line_duration = int(duration * len(line) / total_chars) if total_chars > 0 else 0 + line_end = min(current_ms + line_duration, ed) + result.append((current_ms, line_end, line)) + current_ms = line_end + + return result diff --git a/cca/src/segment_splitter.py b/cca/src/segment_splitter.py new file mode 100644 index 0000000..eebff97 --- /dev/null +++ b/cca/src/segment_splitter.py @@ -0,0 +1,179 @@ +# -*- coding: utf-8 -*- +""" +节目结构切分器 — 将 ASR 结果按节目结构拆分为 5 段 + +结构: 导视 + 正片(3段) + 下期预告 +标志词: +- 导视结束 / 正片开始: "各位观众你们好" 或 "我是主持人蓝皓" +- 正片结束: "好了观众朋友们" 或 "感谢您.*关注.*军事科技" +- 正片之后 = 下期预告 + +正片拆3段: 按时长大致均分,优先在角色转换处(speaker_id 变化)切分 +""" + +import re +from typing import List, Tuple, Optional + +# 标志词模式 +PATTERN_SHOW_START = re.compile(r"各位观众你们好|我是主持人蓝皓") +PATTERN_SHOW_END = re.compile(r"好了观众朋友们|感谢您.*关注.*军事科技|感谢您持续关注") + + +def find_segment_boundaries( + sentences: List[Tuple[int, int, str, int]], +) -> Tuple[int, int]: + """ + 找到正片开始和结束的句子索引。 + 返回 (show_start_idx, show_end_idx) + - show_start_idx: "各位观众你们好"所在句子的索引 + - show_end_idx: "好了观众朋友们"所在句子的索引 + """ + show_start_idx = 0 + show_end_idx = len(sentences) - 1 + + for i, (_, _, text, _) in enumerate(sentences): + if PATTERN_SHOW_START.search(text): + show_start_idx = i + break + + for i in range(len(sentences) - 1, -1, -1): + _, _, text, _ = sentences[i] + if PATTERN_SHOW_END.search(text): + show_end_idx = i + break + + return show_start_idx, show_end_idx + + +def split_show_into_three( + sentences: List[Tuple[int, int, str, int]], + start_idx: int, + end_idx: int, +) -> Tuple[int, int]: + """ + 将正片(start_idx 到 end_idx)拆成 3 段。 + 返回两个切分点索引 (split1_idx, split2_idx) + + 策略: 按时长三等分,然后在附近找 speaker_id 变化的位置。 + """ + if end_idx - start_idx < 6: + # 太短了,均分 + third = (end_idx - start_idx) // 3 + return start_idx + third, start_idx + 2 * third + + show_start_ms = sentences[start_idx][0] + show_end_ms = sentences[end_idx][1] + total_duration = show_end_ms - show_start_ms + + target1_ms = show_start_ms + total_duration // 3 + target2_ms = show_start_ms + 2 * total_duration // 3 + + split1 = _find_best_split(sentences, start_idx, end_idx, target1_ms) + split2 = _find_best_split(sentences, split1 + 1, end_idx, target2_ms) + + # 确保 split2 > split1 + if split2 <= split1: + split2 = split1 + (end_idx - split1) // 2 + + return split1, split2 + + +def _find_best_split( + sentences: List[Tuple[int, int, str, int]], + range_start: int, + range_end: int, + target_ms: int, + search_window: int = 15, +) -> int: + """ + 在 target_ms 附近(±search_window 句)找最佳切分点。 + 优先找 speaker_id 变化的位置,其次找 >2秒 空白。 + """ + # 先找到时间上最接近 target_ms 的句子 + closest_idx = range_start + min_diff = abs(sentences[range_start][0] - target_ms) + for i in range(range_start, min(range_end + 1, len(sentences))): + diff = abs(sentences[i][0] - target_ms) + if diff < min_diff: + min_diff = diff + closest_idx = i + + # 在附近找 speaker 变化点 + search_lo = max(range_start + 1, closest_idx - search_window) + search_hi = min(range_end, closest_idx + search_window) + + best_idx = closest_idx + best_score = 0 + + for i in range(search_lo, search_hi): + score = 0 + # speaker 变化加分 + if sentences[i][3] != sentences[i - 1][3] and sentences[i][3] != 0: + score += 10 + # 空白间隔加分 + gap = sentences[i][0] - sentences[i - 1][1] + if gap > 2000: + score += 5 + elif gap > 1000: + score += 2 + # 离目标越近加分 + time_diff = abs(sentences[i][0] - target_ms) + time_score = max(0, 5 - time_diff / 10000) + score += time_score + + if score > best_score: + best_score = score + best_idx = i + + return best_idx + + +def split_into_segments( + sentences: List[Tuple[int, int, str, int]], +) -> List[Tuple[str, List[Tuple[int, int, str, int]]]]: + """ + 将全部 ASR 句子拆分为 5 段。 + 返回: [("导视", [...]), ("正片1", [...]), ("正片2", [...]), ("正片3", [...]), ("预告", [...])] + + 如果找不到标志词,则只输出单段。 + """ + if not sentences: + return [("正片1", [])] + + show_start_idx, show_end_idx = find_segment_boundaries(sentences) + + # 导视: 0 到 show_start_idx-1 + intro = sentences[:show_start_idx] if show_start_idx > 0 else [] + + # 正片: show_start_idx 到 show_end_idx + show_sentences = sentences[show_start_idx:show_end_idx + 1] + + # 预告: show_end_idx+1 到末尾 + trailer = sentences[show_end_idx + 1:] if show_end_idx < len(sentences) - 1 else [] + + # 正片拆3段 + if len(show_sentences) > 6: + split1, split2 = split_show_into_three(sentences, show_start_idx, show_end_idx) + # 转为相对于 show_sentences 的索引 + rel_split1 = split1 - show_start_idx + rel_split2 = split2 - show_start_idx + show_part1 = show_sentences[:rel_split1] + show_part2 = show_sentences[rel_split1:rel_split2] + show_part3 = show_sentences[rel_split2:] + else: + show_part1 = show_sentences + show_part2 = [] + show_part3 = [] + + segments = [] + if intro: + segments.append(("导视", intro)) + segments.append(("正片1", show_part1)) + if show_part2: + segments.append(("正片2", show_part2)) + if show_part3: + segments.append(("正片3", show_part3)) + if trailer: + segments.append(("预告", trailer)) + + return segments diff --git a/cca/src/srt_writer.py b/cca/src/srt_writer.py new file mode 100644 index 0000000..e092244 --- /dev/null +++ b/cca/src/srt_writer.py @@ -0,0 +1,49 @@ +# -*- coding: utf-8 -*- +""" +SRT 生成器 — 将折行后的字幕行列表写成大洋系统兼容的 SRT 文件 + +格式参照 data/ 下的真实样本: +- 序号从 1 开始 +- 时间格式: HH:MM:SS,mmm --> HH:MM:SS,mmm +- 每条字幕一行文字(不多行) +- 空白行(屏幕清字幕)写为空内容 +- 条目之间用空行分隔 +""" + +from typing import List, Tuple + + +def ms_to_srt_time(ms: int) -> str: + """毫秒 → SRT 时间格式 HH:MM:SS,mmm""" + if ms < 0: + ms = 0 + hours = ms // 3600000 + minutes = (ms % 3600000) // 60000 + seconds = (ms % 60000) // 1000 + millis = ms % 1000 + return f"{hours:02d}:{minutes:02d}:{seconds:02d},{millis:03d}" + + +def write_srt( + subtitle_lines: List[Tuple[int, int, str]], + output_path: str, + time_offset: int = 0, +) -> None: + """ + 写入 SRT 文件 + + subtitle_lines: [(start_ms, end_ms, text), ...] text="" 表示空白行 + output_path: 输出文件路径 + time_offset: 时间偏移(用于正片拆分后各段从0开始计时的情况,这里不用,保持绝对时间) + """ + with open(output_path, "w", encoding="utf-8") as f: + for idx, (start_ms, end_ms, text) in enumerate(subtitle_lines, 1): + start = ms_to_srt_time(start_ms - time_offset) + end = ms_to_srt_time(end_ms - time_offset) + f.write(f"{idx}\n") + f.write(f"{start} --> {end}\n") + # 空白行写一个空格(参照样本中的做法) + f.write(f"{text if text else ' '}\n") + f.write("\n") + + print(f"[SRT] 已写入: {output_path} ({len(subtitle_lines)} 条)") diff --git a/cca/test_local.py b/cca/test_local.py new file mode 100644 index 0000000..8564937 --- /dev/null +++ b/cca/test_local.py @@ -0,0 +1,136 @@ +# -*- coding: utf-8 -*- +""" +本地测试 — 不需要讯飞凭证 +用模拟的 ASR 数据测试折行引擎和 SRT 生成 +""" + +import sys +from pathlib import Path + +sys.path.insert(0, str(Path(__file__).parent / "src")) + +from line_breaker import break_sentence, clean_punctuation, process_sentences +from srt_writer import write_srt, ms_to_srt_time +from segment_splitter import split_into_segments, find_segment_boundaries + + +def test_clean_punctuation(): + print("=== 测试标点清理 ===") + cases = [ + ('对于战后日本而言,重新武装最大的限制不是工业能力,而是政治约束。', '对于战后日本而言重新武装最大的限制不是工业能力而是政治约束'), + ('这是“和平宪法”的约束', '这是“和平宪法”的约束'), + ('你好!世界?', '你好世界'), + ] + for input_text, expected in cases: + result = clean_punctuation(input_text) + status = "✓" if result == expected else "✗" + print(f" {status} 输入: {input_text}") + print(f" 结果: {result}") + if result != expected: + print(f" 期望: {expected}") + print() + + +def test_break_sentence(): + print("=== 测试折行 ===") + cases = [ + "对于战后日本而言重新武装最大的限制不是工业能力而是政治约束", + "各位观众你们好欢迎收看军事科技我是主持人蓝皓", + "F-35B隐身战斗机", + "日本通过从美国引进F-35战机和战斧巡航导弹等先进装备迅速获得了第五代战机远程精确打击能力", + ] + for text in cases: + lines = break_sentence(text) + print(f" 输入 ({len(text)}字): {text}") + for line in lines: + print(f" → [{len(line):2d}字] {line}") + # 验证每行不超过14字 + for line in lines: + assert len(line) <= 14, f"超过14字: {line} ({len(line)}字)" + print() + + +def test_process_sentences(): + print("=== 测试完整折行流程 ===") + # 模拟 ASR 句子(参照 data/1.srt 内容) + sentences = [ + (8520, 8840, "", 0), # 空句 + (8880, 9880, "各位观众你们好", 1), + (9920, 11320, "欢迎收看军事科技", 1), + (11360, 12280, "我是主持人蓝皓", 1), + (12320, 13120, " ", 0), # 空白 + (13160, 14400, "日本国会参议院", 1), + (14440, 16000, "今天上午6月26日表决通过了", 1), + (16040, 18480, "防卫省设置法修正案等法案", 1), + # 模拟 >2秒空白 + (22000, 24320, "这是日本自1954年", 1), + (24360, 29040, "成立陆上海上航空自卫队以来", 1), + ] + + result = process_sentences(sentences) + print(f" 输入 {len(sentences)} 句 → 输出 {len(result)} 行") + for start, end, text in result: + time_str = f"{ms_to_srt_time(start)} --> {ms_to_srt_time(end)}" + print(f" {time_str} {text if text else '[空白]'}") + print() + + +def test_segment_detection(): + print("=== 测试节目结构识别 ===") + sentences = [ + (0, 5000, "本期军事科技将为您介绍", 1), + (5000, 8000, "日本军备的发展历程", 1), + (8880, 9880, "各位观众你们好", 1), + (9920, 11320, "欢迎收看军事科技", 1), + (11360, 12280, "我是主持人蓝皓", 1), + (13000, 50000, "正片内容一", 1), + (50000, 100000, "正片内容二", 2), + (100000, 150000, "正片内容三", 1), + (150000, 200000, "正片内容四", 2), + (200000, 250000, "正片内容五", 1), + (250000, 300000, "正片内容六", 2), + (300000, 310000, "好了观众朋友们感谢您持续关注国防军事频道军事科技", 1), + (310000, 320000, "下期我们将继续关注", 1), + (320000, 330000, "某某话题", 1), + ] + + start_idx, end_idx = find_segment_boundaries(sentences) + print(f" 正片开始: 第{start_idx}句 = {sentences[start_idx][2]}") + print(f" 正片结束: 第{end_idx}句 = {sentences[end_idx][2]}") + + segments = split_into_segments(sentences) + for name, seg in segments: + if seg: + print(f" [{name}] {len(seg)}句, 时间 {ms_to_srt_time(seg[0][0])} ~ {ms_to_srt_time(seg[-1][1])}") + else: + print(f" [{name}] 空") + print() + + +def test_srt_output(): + print("=== 测试 SRT 输出 ===") + subtitle_lines = [ + (8880, 9880, "各位观众你们好"), + (9920, 11320, "欢迎收看《军事科技》"), + (11360, 12280, "我是主持人蓝皓"), + (12320, 13120, ""), # 空白行 + (13160, 14400, "日本国会参议院"), + ] + + output_path = Path(__file__).parent / "output" / "test.srt" + output_path.parent.mkdir(exist_ok=True) + write_srt(subtitle_lines, str(output_path)) + + # 读回来检查 + content = output_path.read_text(encoding="utf-8") + print(content[:500]) + print() + + +if __name__ == "__main__": + test_clean_punctuation() + test_break_sentence() + test_process_sentences() + test_segment_detection() + test_srt_output() + print("=== 全部测试完成 ===") diff --git a/note/寄存条CCA唱词助手子项目已外迁.md b/note/寄存条CCA唱词助手子项目已外迁.md new file mode 100644 index 0000000..7431a7a --- /dev/null +++ b/note/寄存条CCA唱词助手子项目已外迁.md @@ -0,0 +1,78 @@ +# 寄存条:CCA 唱词助手子项目已外迁 + +> 留在主 project,让未来的 Claude 一眼知道:CCA 唱词助手模块已拉出去单独立项了。 +> 外迁时间:2026-07-04 + +--- + +## 外迁了什么 + +**CCA 唱词助手**(ChangCi Assist)整体作为子项目。 + +聚焦:编导 A 稿专有名词提取 → 讯飞 ASR 转写 → AI 校对比对 → 编导审稿台 → 拍词折行 → 大洋格式 SRT 输出。 + +目的:编导剪完节目后,半自动生成唱词字幕 SRT 文件,交责编上大洋系统。 + +--- + +## 主 project 不再讨论的话题 + +聊到下面这些词,**先问一句"这是 CCA 子项目的事还是主 project 的事?"**——是子项目的事,提醒制片人切到 CCA 子项目 chat。 + +关键词:cca / 唱词助手 / changci / SRT 字幕 / 拍词规则 / 编导审稿台 / 唱词校对 / ASR 转字幕 / 大洋字幕格式 / 折行规则 / 审稿对比 + +--- + +## 主 project 仍在管什么 + +- Phase 0-3 已落地的主干代码(episodes、editors、收视诊断、知识库) +- backend 全部 schema、API、迁移脚本 +- 前端全部 React 代码实施 +- 主干 Bug、性能优化、新需求(CCA 以外的) +- CCA 成熟后并入 TPS 的对接方案(届时再定) +- 看板分析升级 / Doco 文稿整理等其他子项目 + +--- + +## 与 Doco 子项目的区别 + +| | Doco | CCA | +|---|---|---| +| **时间点** | 播出后 | 剪辑后、播出前 | +| **目的** | 整理终版文稿(存档/知识库) | 生成唱词字幕 SRT(上大洋播出) | +| **输入** | A稿 + 视频(含字幕+人声) | A稿 + 纯人声音频 | +| **输出** | 融合 A 稿 docx | SRT 字幕文件 | +| **ASR 角色** | 辅助参照 | 核心底稿(时间戳+内容基准) | +| **共同点** | 都用讯飞录音文件转写标准版 + 热词偏置 | + +--- + +## 接收子项目交付物的接口 + +CCA 最终要并入 TPS 主项目作为子功能。接口约定: + +- **独立 Web 应用**:先在 lanhao 配音 2.0 部署测试 +- **并入路径**:成熟后以子功能形式嵌入 TPS 前端,走主项目路由 +- **凭证管理**:子项目自己 .env,主项目 `api_credentials_inventory.md` 登记元信息 + +**纪律**: +- 并入前,子项目不改主项目 backend 代码 / schema +- 并入方案由主项目侧审批 +- 实施完成后回访子项目登记状态 + +--- + +## 开局口径 + +进主 project 新 chat: +> "续接 TPS 主项目。读 `寄存条CCA唱词助手子项目已外迁.md` 和其他寄存条。当前要做 [具体任务]。" + +--- + +## 当前外迁的子项目清单(随更新) + +| 子项目 | 外迁日期 | 寄存条文件 | 状态 | +|---|---|---|---| +| TPS 看板分析升级 | 2026-06-12 | `寄存条_看板升级已外迁.md` | 原型阶段收工(2026-07-03) | +| Doco 文稿整理 | 2026-06-12 | `寄存条Doco文稿整理子项目已外迁.md` | 开发收尾(2026-07-03) | +| CCA 唱词助手 | 2026-07-04 | 本文件 | **立项,待开发** | diff --git a/note/寄存条Doco文稿整理子项目已外迁.md b/note/寄存条Doco文稿整理子项目已外迁.md index bcd2660..64cd390 100644 --- a/note/寄存条Doco文稿整理子项目已外迁.md +++ b/note/寄存条Doco文稿整理子项目已外迁.md @@ -103,4 +103,5 @@ Doco 子项目交付物的接口约定,见**子项目主 Brief §六**(交付什 | 子项目 | 外迁日期 | 寄存条文件 | 状态 | | ---------------- | ---------- | -------------------------- | ------------------------- | | TPS 看板分析升级 | 2026-06-12 | `寄存条_看板升级已外迁.md` | 原型阶段收工(2026-07-03) | -| Doco 文稿整理 | 2026-06-12 | 本文件 | **开发收尾(2026-07-03)**:22 期融合A稿已产出,成品在 `doco/deliverables/`,待批量导入主项目知识库 | \ No newline at end of file +| Doco 文稿整理 | 2026-06-12 | 本文件 | **开发收尾(2026-07-03)**:22 期融合A稿已产出,成品在 `doco/deliverables/`,待批量导入主项目知识库 | +| CCA 唱词助手 | 2026-07-04 | `寄存条CCA唱词助手子项目已外迁.md` | **立项,待开发** | \ No newline at end of file