Try   HackMD

[FFmpeg] 烙印字幕至影像上 (Hardsub)

簡介

如果你的播放設備不支援字幕 (softsub, 也就是封裝在影片內的字幕) ,你就要重新編碼視訊將字幕烙印在畫面上 (hardsub),播放時一定有字幕,因為字幕是烙印在畫面上,只要有畫面就有字幕。

字幕篩選器

要將字幕烙印至影像上做成 Hardsub 必須使用到 libass (subtitles 篩選器),ffmpeg 的 configuration 如果含有 --enable-libass 則代表 libass 是可用的。

要將字幕烙印至影像上,必須要重新編碼視訊才可以,所以不能使用 -codec:v copy-c:v copy-vcodec copy 來複製視訊串流。注意,subtitles filter 只能指定輸入字幕檔名,無法指定路徑,所以必須將字幕檔放置在工作目錄下。

將 ASS 字幕做成 Hardsub:

ffmpeg -input.mp4 -vf "subtitles=filename='sub.ass'" output.mp4

若輸入檔名為第一個選項,可以省略 filename=, f=

ffmpeg -input.mp4 -vf "subtitles='sub.srt'" output.mp4

從輸入影片內讀取第1個字幕 (s:0)做成 Hardsub:

ffmpeg -input.mkv -vf "subtitles=input.mkv:si=0" output.mkv

如果需要強制指定字幕的樣式,可以先使用 Aegisub 在字幕內設定所需樣式幕並另存為 ASS 檔,再給 FFmpeg 處理。或者可以使用 subtitles 篩選器的 force_style 選項。

強制覆蓋字幕樣式:

-vf "subtitles='sub.srt':force_style='FontName=Microsoft JhengHei,FontSize=20,PrimaryColour=&HAA00FF00'"

字體變形問題

若 subtitles 篩選器的輸入影像不是正方形像素(PAR 1:1),這會導致輸出字幕寬高比例錯誤。

假設 input.mkv 為 1280x720 [PAR 1:1 DAR 16:9] 轉成 704x480:

ffmpeg -i input.mkv -vf "scale='w=704:h=480',subtitles='sub.srt'" output.mkv

input.mkv (1280x720 [PAR 1:1 DAR 16:9]) → scale (704x480 [PAR 40:33 DAR 16:9]) → subitles → output.mkv

由於 scale 的輸出與輸入解析度不同,將自動改變 PAR 使 DAR 與輸入相同為 16:9,這使 subtitles 的輸入像素寬高(PAR)比不是 1:1,輸出字幕將會得到錯誤的寬高比。

註:DAR = Width / Height * PAR

以下介紹三種解決方式

指定字幕原始大小

使用 subtitles filter 的 original_size 參數指定影像解析度讓字幕寬高正常縮放。

承上,已知 subtitles 的輸入影像為 704x480 [PAR 40:33 DAR 16:9]

=48016/9=853.333...

設定字幕原始大小 854x480:

ffmpeg -i input.mkv -vf "scale='w=704:h=480',subtitles='sub.srt':original_size='854x480'" output.mkv

篩選器鏈順序

改變 subitles filter 順序使其輸入為正方形像素 (PAR 1:1) 的影像。

subtitles 移動到 scale 之前:

ffmpeg -i input.mkv -vf "subtitles='sub.srt',scale='w=704:h=480'" output.mkv

input.mkv (1280x720 [PAR 1:1 DAR 16:9]) → subitles → scale (704x480 [PAR 40:33 DAR 16:9]) → 字體比例正常

編輯字幕

已知輸出字幕會被縱向壓扁,那麼只要編輯字幕先將字體橫向壓扁,如此一來之後被縱向壓扁後,字體寬高會變回正常。如果字幕是 ASS/SSA 格式,編輯字幕風格將 ScaleX, ScaleY 設為 82, 100 即可。

PAR=1/1

PAR=(16/9)/(704/480)=40/33

=/=(1/1)/(33/40)=0.825

將編輯後 ASS 字幕做成 Hardsub:

ffmpeg -i input.mkv -vf "scale='w=704:h=480',subtitles='sub.ass'" output.mkv

以圖片為基礎的字幕

由於目前 subtitles filter 只能使用 ASS/SSA、SRT 之類的文字字幕,若字幕為 "以圖片為基礎" 的格式,例如,Blu-ray 字幕 (hdmv_pgs_subtitle) 或 DVD 字幕 (dvdsub) 是以圖片為基礎的類型,你可以透過使用 overlay filter 將字幕覆蓋至影像上。

將 M2TS 內的視訊與字幕串流結合為一個視訊串流:

ffmpeg -i input.m2ts -filter_complex "[0:v][0:s]overlay[v]" -map "[v]" -map 0:a -c:v libx264 -c:a copy output.mkv

假設 M2TS 檔案內有多個字幕串流,如果要挑選第二個字幕串流可以使用 "0:s:1" 這樣的串流說明符:

ffmpeg -i input.m2ts -filter_complex "[0:v][0:s:1]overlay[v]" -map "[v]" -map 0:a -c:v libx264 -c:a copy output.mkv
tags: ffmpeg