name: ym-mediatoolkit version: 4.3.1 description: 自然語言媒體助手 - 影片壓縮、MP4/MOV 封面提取、音訊轉換、字幕識別 author: your_name tags: - video - compression - thumbnail - audio - streaming - ffmpeg categories: - media - utility clawhub: entrypoint: python run.py runtime: python3 http_port: 8080
自然語言媒體助手,支援從遠端影片 URL、當前工作目錄內的本地影片檔案、或配置過 media_roots 的本地媒體目錄直接處理:
pip install -r requirements.txt
系統需要安裝:
ffmpeg
ffprobe
字幕識別依賴已內建在 requirements.txt,包括 faster-whisper、paddlepaddle、paddleocr。
維護、釋出、測試和排障流程見 MAINTENANCE.md。
python run.py -a <action> -i '<json>'
也可以從 JSON 檔案讀取引數:
python run.py -i params.json
python run.py --serve
預設監聽 127.0.0.1:8080。
健康檢查:
GET /health
非同步長任務:
POST /skill/jobs
GET /skill/jobs/<job_id>
GET /skill/jobs
輸入源欄位可使用 video_url、url 或 source,三者等價。遠端輸入僅支援 http/https,本地輸入預設限制在當前工作目錄內;需要訪問絕對路徑時,通過請求引數 media_roots 或環境變數 YM_MEDIA_ROOTS 配置允許的媒體根目錄。
從 4.1.0 開始,所有 action 都會返回穩定協議欄位:
| 欄位 | 說明 |
|---|---|
status |
success / partial / skipped / error |
code |
穩定機器碼,例如 ok、missing_source、output_exists、parse_failed |
reply |
適合聊天展示的簡短中文回覆 |
hint |
面向呼叫方或使用者的下一步建議 |
原有業務欄位會繼續保留,例如 output_path、saved_path、outputPath、manifest_path、info、captions、result。
預設輸出目錄:
| 型別 | 預設目錄 |
|---|---|
| 壓縮影片 | output/videos |
| 音訊 | output/audio |
| 封面 | output/thumbs |
所有會寫檔案的介面都支援 overwrite,預設 true。設定為 false 時,如果輸出檔案已存在會直接返回錯誤。
video_url / url / source 三種輸入欄位。output/videos、output/audio、output/thumbs。overwrite 覆蓋策略,避免誤覆蓋已有檔案。chat,適合 Claw 直接轉發使用者聊天文本。訪問小蔥技能站7w4.net,解鎖更多實用的AI技能外掛。
media_roots 白名單,支援處理授權目錄內的絕對路徑檔案。chat 返回 reply 和結構化 result,同時兼顧聊天展示和自動化消費。subtitle 推薦入口,支援 asr / ocr / fusion 模式。asr 和 ocr 單獨除錯入口。captionTxt、startTimeUs、endTimeUs、source、confidence。chat 支援“識別字幕 / 提取字幕 / 轉字幕 / 生成字幕”等自然語言命令。faster-whisper、paddlepaddle、paddleocr 納入預設 requirements.txt。code、reply、hint,方便 Claw 和後續渠道適配。missing_source、source_not_allowed、output_exists、parse_failed、missing_steps、unsupported_action、ffmpeg_failed、missing_asr_dependency、missing_ocr_dependency。caption_segment,用於 emlet 字幕二次分句。12 個字元,按強標點、弱標點、連線詞和長度切分。protected_terms 和 protected_terms_path,用於保護品牌詞、產品名、人名、術語不被拆開。pipeline 支援 subtitle -> caption_segment 串聯;分句步驟未傳 caption_path 時會自動使用上一步字幕 JSON。/skill/jobs,適合壓縮、ASR/OCR、字幕和 pipeline 等耗時 action。output/jobs/<job_id>/job.json,支援提交、輪詢和列表查詢。/skill/<action> 同步介面保持不變;CLI 仍保持同步執行。chat 增加 HTTP 非同步閉環:async=true 會把識別出的 action 提交為 job。async="auto" 會自動將 audio、compress、asr、ocr、subtitle、caption_segment、batch、pipeline 作為非同步長任務執行;info、audio_info、thumbnail 保持同步返回。created_by、intent、source、metadata,方便 Claw 按聊天上下文展示結果。wait_timeout_sec 內完成時返回 200 和最終結果;仍在排隊或執行時返回 202。/skill/jobs 嚴格要求 params 為 JSON object;預設或 null 使用 {},陣列、字串等返回 invalid_params。async 僅接受 JSON boolean 或 "auto";wait_timeout_sec 必須是 0-30 秒數字。output_paths 會按首次出現順序去重。Action: chat
Claw 推薦優先呼叫 chat。普通短命令可同步呼叫;壓縮、字幕、pipeline 等長任務推薦 HTTP 呼叫時傳入 async:"auto"。複雜、確定性要求高的多步驟流程繼續使用 pipeline。
python run.py -a chat -i '{"message":"將 \"sample.mp4\" 提取音訊"}'
python run.py -a chat -i '{"message":"給 \"sample.mp4\" 提取第 3 秒封面"}'
python run.py -a chat -i '{"message":"壓縮 \"sample.mp4\""}'
python run.py -a chat -i '{"message":"檢視 \"sample.mp4\" 資訊"}'
python run.py -a chat -i '{"message":"識別 \"sample.mp4\" 的字幕"}'
HTTP / Claw 長任務推薦:
curl -X POST http://127.0.0.1:8080/skill/chat \
-H 'Content-Type: application/json' \
-d '{"message":"識別 \"sample.mp4\" 的字幕","async":"auto"}'
返回會包含 job_id、poll_url、job_path,隨後輪詢 poll_url 獲取 reply、result 和 output_paths。如需全部自然語言命令都進入 job,可傳 async:true;如需短等待,可傳 wait_timeout_sec。排隊或執行中的非同步響應返回 HTTP 202,短等待內已完成的非同步響應返回 HTTP 200。
處理絕對路徑時需要配置媒體根目錄:
python run.py -a chat -i '{"message":"將 \"D:/AA.MP4\" 提取音訊","media_roots":["D:/"]}'
返回包含:
| 欄位 | 說明 |
|---|---|
reply |
可直接展示給使用者的聊天回覆 |
intent |
識別出的意圖 |
action |
實際呼叫的 action |
params |
傳給底層 action 的引數 |
result |
底層 action 原始結果 |
output_paths |
本次生成的輸出路徑列表 |
job_id |
非同步提交時的任務 id |
poll_url |
非同步提交後的輪詢地址 |
Action 可以繼續同步呼叫,也可以通過 job API 非同步執行。推薦對 compress、asr、ocr、subtitle、pipeline 等長任務使用非同步介面。
提交任務:
curl -X POST http://127.0.0.1:8080/skill/jobs \
-H 'Content-Type: application/json' \
-d '{"action":"pipeline","params":{"source":"sample.mp4","steps":[{"id":"metadata","action":"info","enabled":true}]}}'
params 必須是 JSON object;不傳或傳 null 時按 {} 處理。
返回:
{
"status": "queued",
"code": "ok",
"reply": "任務已提交:<job_id>",
"job_id": "<job_id>",
"job_path": "output/jobs/<job_id>/job.json",
"poll_url": "/skill/jobs/<job_id>"
}
輪詢任務:
curl http://127.0.0.1:8080/skill/jobs/<job_id>
任務狀態包括:queued、running、success、partial、skipped、error。任務結果儲存在 result,產物路徑彙總在 output_paths。
查詢任務列表:
curl 'http://127.0.0.1:8080/skill/jobs?status=success&limit=50'
任務檔案儲存在 output/jobs/<job_id>/job.json。服務重啟後,已完成任務仍可查詢;未完成的 queued / running 任務會標記為 error,code=job_interrupted。
Action: subtitle
推薦使用 subtitle,預設 mode=fusion:ASR 負責主要時間軸和文本,OCR 做畫面字幕校正。識別依賴隨 requirements.txt 安裝;如果環境未重新安裝依賴,會返回 JSON error,不會拋未捕獲異常。
python run.py -a subtitle -i '{"source":"sample.mp4","mode":"fusion"}'
python run.py -a subtitle -i '{"source":"sample.mp4","mode":"asr","language":"zh"}'
python run.py -a subtitle -i '{"source":"sample.mp4","mode":"ocr","sample_interval_sec":1}'
引數:
| 引數 | 型別 | 預設值 | 說明 |
|---|---|---|---|
video_url / url / source |
string | 必填 | 遠端 URL 或本地檔案 |
mode |
string | fusion | asr / ocr / fusion |
language |
string | auto | ASR 語言,例:zh / en |
model_size |
string | base | faster-whisper 模型規格 |
sample_interval_sec |
number | 1.0 | OCR 抽幀間隔 |
crop_bottom_ratio |
number | 0.35 | OCR 預設掃描畫面下方比例 |
output_path |
string | output/subtitles/... |
字幕 JSON 輸出路徑 |
overwrite |
boolean | true | 是否覆蓋已有檔案 |
字幕條目格式:
{
"captionTxt": "識別到的字幕文本",
"startTimeUs": 1000000,
"endTimeUs": 2000000,
"source": "asr",
"confidence": 0.92
}
底層除錯入口:
python run.py -a asr -i '{"source":"sample.mp4","language":"zh"}'
python run.py -a ocr -i '{"source":"sample.mp4"}'
Action: caption_segment
caption_segment 是 emlet 字幕分句器:它不重新識別字幕,只處理已有 captions。預設 max_chars=12,輸出仍是 SRT-like captions JSON。
python run.py -a caption_segment -i '{
"caption_path":"output/subtitles/sample.captions.json",
"max_chars":12,
"protected_terms":["蘋果","華為","吉利"]
}'
也可以直接傳 captions:
python run.py -a caption_segment -i '{
"captions":[
{"captionTxt":"今天我們聊蘋果華為和吉利的新產品","startTimeUs":0,"endTimeUs":3000000}
],
"max_chars":12,
"protected_terms":"蘋果,華為,吉利"
}'
長期詞庫可以放在 JSON 檔案中:
{
"brands": ["蘋果", "華為", "吉利"],
"products": ["小米汽車", "Model Y", "ChatGPT"]
}
引數:
| 引數 | 型別 | 預設值 | 說明 |
|---|---|---|---|
caption_path / input_path |
string | - | 已有 captions JSON 檔案 |
captions |
array | - | 直接傳入字幕條目 |
max_chars |
integer | 12 | 單條字幕最大字元數 |
protected_terms |
array/string | [] | 不拆開的品牌詞、產品名、人名、術語 |
protected_terms_path |
string | - | 當前工作目錄內的保護詞 JSON 檔案 |
auto_protect_ascii |
boolean | true | 自動保護英文、數字、型號、URL、路徑 |
output_path |
string | output/subtitles/... |
分句後字幕 JSON 輸出路徑 |
overwrite |
boolean | true | 是否覆蓋已有檔案 |
Action: compress
python run.py -a compress -i '{"source":"sample.mp4","target_ratio":0.1}'
引數:
| 引數 | 型別 | 預設值 | 說明 |
|---|---|---|---|
video_url / url / source |
string | 必填 | 遠端 URL 或本地檔案 |
target_ratio |
number | 0.1 | 目標體積比例 |
adaptive |
boolean | true | 是否自動嘗試不同 CRF |
crf |
integer | 24 | 非 adaptive 模式下使用 |
preset |
string | veryfast | ffmpeg 編碼預設 |
output_path |
string | output/videos/... |
輸出路徑 |
overwrite |
boolean | true | 是否覆蓋已有檔案 |
Action: thumbnail
當前支援 MP4/MOV 容器,主要適用於 H.264/H.265 影片軌道。
python run.py -a thumbnail -i '{"source":"sample.mp4","time_seconds":5}'
引數:
| 引數 | 型別 | 預設值 | 說明 |
|---|---|---|---|
video_url / url / source |
string | 必填 | 遠端 URL 或本地檔案 |
time_seconds |
number | 0 | 按時間點提取 |
frame_number |
integer | - | 按幀號提取,優先於 time_seconds |
save_path |
string | output/thumbs/... |
儲存路徑 |
resize_width |
integer | - | 輸出寬度 |
quality |
integer | 85 | JPEG 質量 |
overwrite |
boolean | true | 是否覆蓋已有檔案 |
Action: audio
python run.py -a audio -i '{"source":"sample.mp4","format":"mp3"}'
引數:
| 引數 | 型別 | 預設值 | 說明 |
|---|---|---|---|
video_url / url / source |
string | 必填 | 遠端 URL 或本地檔案 |
format |
string | mp3 | mp3 / wav / aac / m4a |
bitrate |
string | 128k | 音訊位元率 |
sample_rate |
integer | 44100 | 取樣率 |
channels |
integer | 2 | 聲道數 |
start_time |
number | - | 開始時間,秒 |
duration |
number | - | 擷取時長,秒 |
output_path |
string | output/audio/... |
輸出路徑 |
overwrite |
boolean | true | 是否覆蓋已有檔案 |
Action: audio_batch
python run.py -a audio_batch -i '{
"videos":[
{"source":"sample1.mp4","name":"video1"},
{"url":"https://example.com/2.mp4","name":"video2"}
],
"output_dir":"output/audio",
"format":"mp3"
}'
Action: batch
python run.py -a batch -i '{
"action":"thumbnail",
"videos":[
{"source":"sample1.mp4","time_seconds":5},
{"url":"https://example.com/2.mp4","time_seconds":10}
]
}'
action 支援:compress、thumbnail、audio。
Action: pipeline
steps 是唯一流程控制入口,沒有寫進 steps 的動作不會執行。支援的 step action:info、thumbnail、audio、compress、audio_info、asr、ocr、subtitle、caption_segment。
python run.py -a pipeline -i '{
"source":"sample.mp4",
"name":"sample",
"output_dir":"output/pipeline/sample",
"overwrite":true,
"steps":[
{"id":"metadata","action":"info","enabled":true},
{
"id":"cover",
"action":"thumbnail",
"enabled":true,
"params":{"time_seconds":3,"resize_width":720}
},
{
"id":"audio_mp3",
"action":"audio",
"enabled":false,
"params":{"format":"mp3","bitrate":"128k"}
}
]
}'
規則:
| 引數 | 型別 | 預設值 | 說明 |
|---|---|---|---|
video_url / url / source |
string | 必填 | 遠端 URL 或本地檔案 |
name |
string | 輸入檔名 | 流水線名稱 |
output_dir |
string | output/pipeline/<name> |
manifest 和預設產物目錄 |
overwrite |
boolean | true | 是否覆蓋已有產物 |
steps |
array | 必填 | 按 JSON 順序執行的步驟 |
每個 step 需要 id、action、enabled。enabled=false 會記錄為 skipped。每次執行都會生成 manifest.json。
python run.py -a info -i '{"source":"sample.mp4"}'
python run.py -a audio_info -i '{"source":"sample.mp4"}'
http / https。media_roots / YM_MEDIA_ROOTS 可授權額外媒體根目錄。這個 Skill 功能很豐富,涵蓋了影片處理的方方面面,自然語言解析能力也比較實用,能聽懂「提取音訊」「壓縮影片」這類簡單指令。返回結果有統一格式,用起來比較規範。不足之處是版本號標註不一致容易造成困惑,而且依賴較重,首次安裝可能需要較長時間和較大儲存空間。另外 HTTP 服務預設只繫結本地,配置絕對路徑時需要額外設定媒體根目錄,對新手不太友好。