Files
simon 60f8c263f2 《新闻联播》每日抓取入库:全链路 + 可移植化 + 定时任务
从 CCTV 主页抓取《新闻联播》,下载 → 转 MP3/WAV → 静音切分 → ASR 识别
→ LLM 校对 → 切分为单条新闻 → 入库 MySQL。

主要内容:
- 全链路:getVideo5 抓取下载、audioRead 转写、deepseek 校对与切分、newsProcess 入库
- 可移植化:配置分层,.env 只放密钥、config.yml 放模型/接入点/路由/参数
- 可换供应商:endpoints(kind/base_url/api_key_env/extra_body)+ routes 按环节选路
- 数据保真:数值事实守卫,校对改动数字/年份/届次则整片回退 ASR 原文;
  识别不完整不发布该日精编,避免半天内容被当成完整一天
- 定时任务:systemd 每天 21:00,失败 21:30 / 22:00 重试;
  只缺切分时只重跑切分(省掉全部 ASR),用 state/.asr_complete_* 标记判定阶段
- 隧道自愈:13306 不通时自动执行 autossh.sh(所有入口共用,systemd 托管时只等待)
- 中间产物每日清理;97 项离线自检(配置/清理/事实守卫/解析/隧道)
2026-09-25 11:17:46 +08:00

137 lines
6.6 KiB
YAML
Raw Permalink Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
# ============================================================================
# xwlb 非敏感配置
# ============================================================================
# 敏感配置(密钥、数据库口令)保留在 .env:
# MYSQL_PASSWORD / DASHSCOPE_API_KEY / DEEPSEEK_API_KEY
#
# 修改本文件后无需改代码;可用 XWLB_CONFIG_FILE 指定其他配置文件。
# 优先级:进程环境变量 > config.yml > 代码内置默认值
# (即为临时试验,可用 `DASHSCOPE_LLM_MODEL=qwen-max python audioRead.py ...` 覆盖)
# ============================================================================
# ---- 数据库(口令在 .env 的 MYSQL_PASSWORD)----
mysql:
# 隧道自愈:端口不通时自动执行下面的脚本(逻辑见 tunnel.py,所有入口都生效)
tunnel:
enabled: 1
script: autossh.sh # 相对项目根
systemd_unit: xwlb-tunnel.service # 该单元 active 时只等待它自动重连,不抢端口
wait_seconds: 30 # 执行后最多等多久
connect_timeout: 2 # 单次 TCP 探测超时
host: localhost
port: 13306 # 经 autossh.sh 隧道时的本地端口(隧道: 13306 -> 远端 3306)
user: myquant
database: myquant
# ---- 目录(相对项目根,也可写绝对路径)----
paths:
video_dir: xwlb_video # mp4 / mp3 中间产物
audio_dir: audio_processing # wav 分片
# ---- 各环节实际使用的模型(集中在此管理)----
models:
asr_model: paraformer-realtime-v2 # 语音识别
correct_model: qwen3.8-flash # ASR 文本校对
split_model: deepseek-flash # 新闻切分 + 标题(API 实测:deepseek-flash / deepseek-v4-pro)
# ============================================================================
# 接入点(base url):换供应商 / 换区域 / 走公司网关或代理,只改这一段
# ============================================================================
# 每个接入点声明三件事:
# kind 协议类型:dashscope=用 dashscope SDK;openai=OpenAI 兼容的 /chat/completions
# *base_url* 服务地址
# api_key_env 该供应商的密钥放在 .env 里的**变量名**(密钥本身不进本文件)
endpoints:
dashscope:
kind: dashscope
# 文本生成(校对)走 HTTP
http_base_url: https://dashscope.aliyuncs.com/api/v1
# 实时语音识别走 WebSocket
websocket_base_url: wss://dashscope.aliyuncs.com/api-ws/v1/inference
api_key_env: DASHSCOPE_API_KEY
# 国际站示例:把上面两行换成
# http_base_url: https://dashscope-intl.aliyuncs.com/api/v1
# websocket_base_url: wss://dashscope-intl.aliyuncs.com/api-ws/v1/inference
deepseek:
kind: openai
base_url: https://api.deepseek.com/v1
chat_completions_path: /chat/completions
api_key_env: DEEPSEEK_API_KEY
# 注意:**切分环节不要关思维链**。同一天(2026-09-23)实测对比:
# 思考开启 27 条 / 正文覆盖率 99.67% / 19k token
# 思考关闭 20 条 / 正文覆盖率 95.34% / 4.7k token
# 关掉省 4 倍 token 但会丢 4.7% 正文、少切 7 条新闻,得不偿失。
# 若确实要关(DeepSeek 用 thinking 字段,写 enable_thinking 会被静默忽略),在此加:
# extra_body:
# thinking: {type: disabled}
qwen:
kind: openai
base_url: https://token-plan.cn-beijing.maas.aliyuncs.com/compatible-mode/v1
chat_completions_path: /chat/completions
api_key_env: QWEN_TOKEN_PLAN
# 校对关思维链:通义/百炼兼容模式用 enable_thinking(实测 4045 → 312 token,约 13 倍,
# 输出仅差一个"的"字、数值无漂移)。校对是机械任务,想不出什么,纯属浪费。
extra_body:
enable_thinking: false
# 每个环节走哪个接入点(值是 endpoints 下的名字)
routes:
asr: dashscope # 语音识别:仅支持 kind=dashscope(paraformer 实时识别协议)
correct: qwen # 文本校对
split: deepseek # 新闻切分
# ---- 换供应商示例:把「校对」换成 OpenAI 兼容的第三方,只需三步 ----
# 1) 上面的 routes.correct 改成 moonshot
# 2) 在 endpoints 下加一段:
# moonshot:
# kind: openai
# base_url: https://api.moonshot.cn/v1
# chat_completions_path: /chat/completions
# api_key_env: MOONSHOT_API_KEY
# 3) models.correct_model 改成对方的模型名(如 kimi-k2-0905-preview)
# 并在 .env 里加 MOONSHOT_API_KEY=...
# 说明:换供应商不影响数值事实守卫(对任何供应商的校对结果都会校验)。
#
# 若某供应商的 OpenAI 兼容地址不带版本号(如 https://my-gateway/llm),
# 直接写进 base_url 即可,代码只做 base_url + chat_completions_path 拼接。
# ---- 语音识别 ----
asr:
sample_rate: 16000
language_hints: [zh, en]
# ---- 音频切分(静音检测 + 合并)----
audio_split:
min_silence_ms: 700 # 超过该静音长度即切分
silence_thresh_db: -40 # 静音阈值(dBFS)
keep_silence_ms: 400 # 切分处保留的静音
max_chunk_ms: 180000 # 单片最长 3 分钟
# ---- LLM 文本校对 ----
llm_correct:
enabled: 1 # 1=开启校对(默认);0=关闭,直接以 ASR 原文作为 news_improve
max_retries: 2 # 失败重试次数(失败后回退原文,不丢分片)
timeout: 120 # 单次调用超时(秒)
max_tokens: 8000
temperature: 0.1
top_p: 0.5
# 思维链开关在接入点(endpoints.*.extra_body)上配置,因为参数名因供应商而异;
# 如需只针对本环节覆盖,可在此加 extra_body: { ... }
# 开启时仍受「数值事实守卫」保护:若校对改动了数字/年份/届次/规划期等,
# 该分片一律回退 ASR 原文(详见 docs/BUGS.md B2 补充说明)
# ---- DeepSeek 新闻切分 ----
llm_split:
max_tokens: 60000 # 首次尝试;推理模型 reasoning 可能占 2 万+,上限要给足(按实际产出计费)
retry_max_tokens: 80000 # 解析失败后强化提示词重试时的上限
temperature: 0.5
timeout: 180 # 单次 HTTP 超时(秒);输出 2 万 token 级别需要更久
max_retries: 3 # 网络/5xx 重试次数(429、5xx 退避重试)
# ---- 任务完成后清理中间产物 ----
cleanup:
after_daily_run: 1 # 1=当天全程任务结束后自动清理;0=不清理
only_on_success: 1 # 1=仅当当天全部成功才清理(失败时保留文件便于重跑)
remove_video: 1 # 删除 paths.video_dir 下所有 mp3 / mp4
remove_audio: 1 # 删除 paths.audio_dir 下所有 wav