﻿# 如何透過 FFmpeg 將 SRT 字幕檔寫入到 MP4 影片檔中

最近嘗試用 Gemini 1.0 Pro 的 API 翻譯了不少影片，品質相當不錯，然後我在想，除了上傳 YouTube 可以附加 SRT 字幕檔之外，有沒有什麼方式可以直接將字幕燒錄到影片上，最後我用 [FFmpeg](https://ffmpeg.org/) 輕鬆的解決嵌入字幕的問題，這篇文章我就來分享幾個不同的嵌入字幕用法。

![](https://stwillblogassets.blob.core.windows.net/files/images/external/stwillblogassets.blob.core.windows.net/a5efe928757d5efb9b5e-5bcabb93-cd94-461e-a86a-f5b1239b0dac.webp)

基本上我們有好幾種方式可以將 `*.srt` 字幕檔嵌入到字幕中，以下是幾個範例：

1.  將字幕「內嵌」到影片中，並透過影片播放器控制字幕的開關
    
    使用 `-c:s mov_text` 參數，可以指定將字幕檔的編碼格式為 `mov_text`，這是 MP4 文件常用的字幕格式。
    
    ```bash
    ffmpeg -i 'video.mp4' -i 'video.zh.srt' -c copy -c:s mov_text 'video.zh.mp4'
    ```
    
    這裡兩個 `-i` 參數都是指定輸入檔路徑，一個為來源影片，一個為來源字幕檔 ，建議用 `*.srt` 格式。
    
2.  將字幕「燒錄」到影片中，影片播放器無法控制字幕的開關
    
    使用 `-vf "subtitles=subtitle.srt"` 可以套用影像過濾器 `-vf` 來燒錄字幕，直接把指定的字幕檔燒錄到影片上 (關不掉的那種)。
    
    ```bash
    ffmpeg -i 'video.mp4' -vf "subtitles=video.zh_TW.srt" -c:a copy 'output.mp4'
    ```
    
    > 這裡的 `subtitle.srt` 是指明要使用的字幕檔。而 `-c:a copy` 則是直接複製 `audio` 資料流，不做任何編碼。
    
3.  將字幕「燒錄」到影片中，但可以自訂字幕的顯示樣式
    
    由於 [FFmpeg](https://ffmpeg.org/) 可以指定的樣式非常多，你幾乎可以調整出任何你想要的字幕樣式，包含文字大小、文字顏色、背景顏色、邊框顏色、邊框寬度、陰影等等，幾乎都可以自訂，功能十分強大。
    
    基本上 [FFmpeg](https://ffmpeg.org/) 在燒錄字幕時，使用的是 [libass](https://github.com/libass/libass) 開源套件，所以其實你很難在 [FFmpeg Filters Documentation](https://ffmpeg.org/ffmpeg-filters.html#subtitles-1) 官方文件找到任何資訊，頂多只能知道有個 `force_style` 選項可以設定而已。這也是我覺得 [FFmpeg](https://ffmpeg.org/) 很難上手的其中一個原因，他真的太複雜了。
    
    我最後從 [ASS File Format Specification](https://aegisub.org/docs/latest/ass_tags/) 找到了所有樣式參數的清單，總共有 `Name`, `Fontname`, `Fontsize`, `PrimaryColour`, `SecondaryColour`, `TertiaryColour`, `BackColour`, `Bold`, `Italic`, `Underline`, `StrikeOut`, `ScaleX`, `ScaleY`, `Spacing`, `Angle`, `BorderStyle`, `Outline`, `Shadow`, `Alignment`, `MarginL`, `MarginR`, `MarginV`, `AlphaLevel`, `Encoding` 共 23 個。這是我找出最權威的資訊來源了！
    
    > 其實我第一時間不到 10 秒鐘就從 ChatGPT 問到了這 23 種 `force_style` 可用的選項，但我實在無法判斷他是不是在胡說八道，所以花了十幾分鐘才找到我要的權威資料！😅
    
    以下這組參數是我調整無數次之後覺得最美觀的字幕樣式，但你其實還可以做出許多特殊的調整！
    
    ```bash
    ffmpeg -i video.mp4 -vf "subtitles=video.zh_TW.srt:force_style='PrimaryColour=0xCCCCCC,BackColour=0x000000,OutlineColour=0x000000,BorderStyle=1,Outline=1,Shadow=0,MarginV=10,Fontsize=14'" -c:a copy output.mp4
    ```
    
    如果你的影片擁有比較雜亂的畫面，那麼你可以改用以下參數，讓整個字幕套上一個不透明的方框(`BorderStyle=3`)：
    
    ```bash
    ffmpeg -i video.mp4 -vf "subtitles=video.zh_TW.srt:force_style='PrimaryColour=0xCCCCCC,BackColour=0x000000,OutlineColour=0x000000,BorderStyle=3,Outline=1,Shadow=0,MarginV=10,Fontsize=14'" -c:a copy output.mp4
    ```
    
    > 如果字太小，也可以調整 `Fontsize` 參數調大字體。
    

### 關於常用 `force_style` 樣式選項的筆記

-   `PrimaryColour`：字體顏色
    
    範例: `PrimaryColour=0xCCCCCC` (淡灰色)
    
    格式: `BBGGRR` (Blue, Green, Red)
    
-   `BackColour`：這是「字幕邊框」或「陰影」的顏色，但不一定是所謂的「背景色」
    
    範例: `BackColour=0x000000` (黑色)
    
    格式: `BBGGRR` (Blue, Green, Red)
    
-   `BorderStyle`：字幕的外框樣式
    
    `BorderStyle` 只有兩個選項 `1` (文字邊框+陰影) 與 `3` (不透明的盒子)
    
    當 `BorderStyle=1` 時，字幕不會壓上一個大的方框當背景色，而是在「文字」的邊緣劃上一個框，像是替文字描邊線的感覺。這種樣式比較適合影片背景較為乾淨的情況下使用。
    
    當 `BorderStyle=3` 時，字幕就會壓上一個大大的方框當背景色，文字是放進這個不透明的盒子中，讓字幕可以更清晰的呈現，不受影片背景物件所影響。
    
-   `Outline`：字幕的外框寬度，預設值為 `1`
    
    `Outline` 可以設定的值為 `0`, `1`, `2`, `3` 與 `4` 這五種。
    
    當 `BorderStyle=1` 時，這個邊框就是文字的「描邊線」的寬度
    
    當 `BorderStyle=3` 時，這個邊框就是「盒子」的邊框寬度
    
-   `OutlineColour`：字幕的外框顏色
    
    範例: `OutlineColour=0x000000` (黑色)
    
    格式: `BBGGRR` (Blue, Green, Red)
    
-   `Shadow`：字幕的陰影寬度
    
    當 `BorderStyle=1` 時，這個 `Shadow` 就是文字的「描邊線」加上「陰影」的寬度，可以設定的值為 `0`, `1`, `2`, `3` 與 `4` 這五種。
    
    字幕的描邊線一定會加上，但看起來像陰影，你如果不要這個描邊線，那就一定要將 `Outline` 設定為 `0`
    
-   `MarginV`：字幕的垂直邊距
    
    這個是從螢幕底部往上移動的距離，數字越大，字幕擺放的位置就越高。
    
-   `Fontsize`：字幕的文字大小，預設值為 `16`
    
    有些時候字幕過長，超出螢幕時，你可以將 `Fontsize` 將字幕的文字大小調小，這樣就可以讓字幕完全顯示在螢幕上。
    

### 相關連結

-   [FFmpeg Filters Documentation](https://ffmpeg.org/ffmpeg-filters.html#subtitles-1)
-   [libass/libass: libass is a portable subtitle renderer for the ASS/SSA (Advanced Substation Alpha/Substation Alpha) subtitle format.](https://github.com/libass/libass)
-   [ASS File Format Specification](https://aegisub.org/docs/latest/ass_tags/)
