
SRT 交付檢查可以先用一份 CSV 清單,核對字幕檔是否存在、對應的來源版本是否正確,以及審核狀態是否完成。下面的 Python 範例處理這些檔案與紀錄問題;字幕翻得對不對、時間軸是否貼合語音,仍要回到播放器檢查。
這篇寫給需要交付多語言影片的製作與工程協作人員。當資料夾裡同時出現 final.srt、final2.srt 和 final_ok.srt,只看檔名很難知道哪一份跟目前影片配套。檢查器的用途,是在上傳前找出應該停下來確認的項目。
先固定一份來源檔。它可以是核准的旁白腳本,也可以是鎖定版本的影片;同一批交付不要混用兩種定義。程式會計算這份檔案的 SHA-256 雜湊值,再與清單中的紀錄比較。
程式把雜湊相符視為來源版本一致;這是交付流程中的檢查條件,不是內容正確、來源可信或字幕已經審核的證明。只要有人替換影片、修改腳本,甚至改了文字檔的換行方式,雜湊都有可能改變。這正是需要重新確認版本的訊號。
清單使用四欄:language 是這份交付指定的語言標籤,source_sha256 記錄字幕所依據的來源,subtitle_file 是相對於清單位置的字幕檔路徑,review_status 則記錄審核結果。只有負責審核的人完成檢查後,才把狀態填為 approved。
語言名稱也要一致。W3C 的語言標籤說明區分語言、文字系統與地區;繁體中文可以使用 zh-Hant。清單中的標籤只是你提供的資料,以下程式不會讀取字幕後猜測它實際使用哪一種語言。
先建立一個交付資料夾,放入核准來源、各語言字幕與清單。不要一邊整理正式資料夾,一邊讓其他人繼續覆寫裡面的字幕;可以先在工作資料夾修訂,確認後再複製到交付資料夾。這樣檢查的是一組確定的檔案,而不是正在變動的內容。
清單每一列代表一份語言交付。例如英文字幕寫 en.srt,繁中字幕寫 zh-Hant.srt;路徑從 CSV 所在位置開始計算,不是從執行指令的終端機目錄開始。若檔案放在 subtitles 子資料夾,就寫成 subtitles/zh-Hant.srt,不要只留下檔名。
可以用試算表編輯清單,但匯出時應確認欄名、逗號分隔與文字編碼。程式使用 utf-8-sig 讀取 CSV,可處理一般 UTF-8 檔案及帶有 BOM 的 UTF-8 匯出檔。不要把整串雜湊改成科學記號,也不要以截短後的前幾碼代替完整值。
審核狀態尚未完成時,保留 pending。這不是一個需要被「修好」才能通過的程式錯誤,而是交付條件尚未滿足。預期語言清單同樣來自任務要求:本次只交英文與繁中,就明確傳入這兩個標籤;不要為了消除「缺少語言」的訊息而刪除尚未做完的需求。
把下面程式存為 check_delivery.py。它使用 Python 標準函式庫,範例採用 hashlib.file_digest,執行環境需 Python 3.11 或更新版本。manifest.csv 與字幕檔放在同一個工作資料夾,或在清單中填入相對路徑。
"""Validate a local subtitle delivery manifest; this does not evaluate translation quality."""
import csv
import hashlib
import sys
from pathlib import Path
def sha256(path):
with Path(path).open('rb') as stream:
return hashlib.file_digest(stream, 'sha256').hexdigest()
def check(manifest, source, expected_languages):
manifest = Path(manifest)
source_hash = sha256(source)
errors, seen = [], set()
required = {'language', 'source_sha256', 'subtitle_file', 'review_status'}
with manifest.open(encoding='utf-8-sig', newline='') as stream:
reader = csv.DictReader(stream)
if not required <= set(reader.fieldnames or []):
return ['missing required CSV columns']
for number, row in enumerate(reader, 2):
lang = row['language'].strip()
if lang in seen:
errors.append(f'row {number}: duplicate language {lang}')
seen.add(lang)
if row['source_sha256'].strip().lower() != source_hash:
errors.append(f'row {number}: source version mismatch')
if row['review_status'].strip() != 'approved':
errors.append(f'row {number}: review not approved')
path = manifest.parent / row['subtitle_file'].strip()
if not path.is_file() or path.stat().st_size == 0:
errors.append(f'row {number}: subtitle missing or empty')
for lang in sorted(expected_languages - seen):
errors.append(f'missing language: {lang}')
for lang in sorted(seen - expected_languages):
errors.append(f'unexpected language: {lang}')
return errors
if __name__ == '__main__':
if len(sys.argv) != 4:
raise SystemExit('Usage: python check_delivery.py manifest.csv source.txt en,zh-Hant')
errors = check(sys.argv[1], sys.argv[2], set(sys.argv[3].split(',')))
print('\n'.join(errors) if errors else 'PASS: manifest checks only')
raise SystemExit(1 if errors else 0)
執行方式如下。最後一個參數明確指定這次預期收到英文與繁體中文兩份字幕,不是從已收到的檔案反推需求。
python check_delivery.py manifest.csv source.txt en,zh-Hant
程式只讀取檔案,不修改字幕。請把它當作內部可信任交付清單的檢查工具,不要直接接收陌生人提供的路徑清單當成公開上傳服務。若要放入產品系統,還需要限制可讀取的目錄、處理權限與檔案讀取錯誤。

清單檢查可以先找出檔案問題,人工仍要對照實際影片與字幕。
本範例用兩個自行建立的字幕檔與一份來源文字檔,在 Windows 的 Python 3.13.3 實際執行。兩筆資料的來源雜湊相符、檔案有內容、語言符合需求,而且審核狀態都是 approved 時,結果為 PASS: manifest checks only。
接著只改第二筆資料:把來源雜湊換成不同值,並將審核狀態改回 pending。程式回報:
row 3: source version mismatch
row 3: review not approved
這裡的第三列包含 CSV 標題列,因此對應第二筆字幕資料。修正時不要只把清單改成能通過的值;應先確認字幕是否確實按照目前來源重做,以及審核者是否看過這一版。
同一組本機檢查也覆蓋了檔案不存在、空檔、重複語言與非預期語言。這些都是構造的測試資料,能說明程式的行為,不能拿來宣稱某個影片工具的翻譯準確率或實際交付成效。
檔案非空,不代表它是有效的 SRT。美國國會圖書館對 SRT 格式的說明整理了序號、時間資訊與字幕文字等基本結構。這個清單檢查器沒有解析那些區塊,也不會找出錯誤的開始時間、漏字或字幕超出影片結尾。
另一個容易誤解的地方是 approved。它只能證明有人把欄位填成這個字,無法替代審核。實務上還應保存審核者、日期與問題紀錄;如果團隊需要追責,應把批准流程交給有身分與權限管理的系統,而不是相信一份任何人都能改的 CSV。
至少保留這幾項人工檢查:
這篇教學為 Leadde 準備。若製作端使用 Leadde.ai,可在自己的交付流程中採用同樣的清單概念;本文程式是獨立範例,不是官方整合,也不代表產品會自動提供這份 CSV。

製作端的腳本與交付端的字幕清單各有用途;此畫面沒有執行本文的 Python 檢查器。
來源一旦變更,先保留舊版與原清單,再為新版建立新的交付紀錄。不要把所有字幕列的來源雜湊一次改掉,讓舊字幕看起來像已經更新。只有完成實際修訂與復核的語言,才更新對應紀錄。
交付前從預定發布的資料夾再跑一次檢查。檔案可能在最後整理時被改名、漏複製,或被另一個同名版本覆蓋。最後開啟影片與字幕抽查,將程式輸出和人工問題紀錄一起保存,才有辦法說明這一包檔案為什麼可以交付。