# [FFmpeg] 定位起始與結束時間 ## 介紹 假如只是要提取輸入的特定的一部份,你需要使用 seeking 選項來得到特定的一部份。 ## 時間碼語法 你可以使用兩種時間單位格式: 六十進位 `HOURS:MM:SS.MICROSECONDS`,例如 `01:23:45.678`,或是秒數。 ## Seeking 使用方式 ### Input seeking 參數 `-ss` 需要被指定在 `-i` 之前位置: ```powershell ffmpeg -ss 00:23:00 -i input.mkv cut.mkv ``` 這個例子將擷取 00:23:00 之後的片段。輸入將使用 keyframes 進行解析,這速度非常快。 當 -ss 作為輸入選項 (位於 `-i` 之前) 時,將會定位到指定時間點並歸零的當前時間戳記,如果有使用 `subtitles` filter,字幕與影音將不會正確同步。 在 FFmpeg 2.1 之後 `-ss` 也是精準畫格(挑轉到指定時間),無論作為輸出或輸入選項。可以使用輸入選項 `-noaccurate_seek` 來恢復之前的特性(跳轉到指定時間前最近的 keyframes,即使時間不準確)。 從 `00:02:00` 之前最接近的 keyframes 開始分割: ```powershell ffmpeg -noaccurate_seek -ss 00:02:00 -i input.mp4 -c copy cut.mp4 ``` ### Output seeking 參數 `-ss` 需要被指定在 `-i` 之後位置: ```powershell ffmpeg -i input.mkv -ss 00:23:00 cut.mkv ``` 這個例子將擷取 `00:23:00` 之後的片段。在這裡,該輸入將被從頭 (`00:00:00`) 解碼 (與丟棄) 直到它到達 `-ss` 所給定的時間點才開始輸出。 ## 分割一部分 如果只是要影片中間提取某一片段,可以搭配使用 `-t` 指定持續時間,例如 `-ss 60` & `-t 10` 可以擷取輸入的 60 至 70 秒片段。或者可以使用 `-to` 指定一個時間點結束寫入輸出, 例如 `-ss 60` & `-to 70` 可以擷取輸入的 60 至 70 秒片段。 `-t` 與 `-to` 是互斥的,如果同時使用兩者,只有 `-t` 會被使用。 > 注意:當 `-ss` 位於 `-i` 之前時,該時間戳記將會被歸零,所以 `-t` 與 `-to` 將會有相同的效果: ```powershell ffmpeg -ss 00:01:00 -i video.mp4 -to 00:02:00 cut.mp4 ffmpeg -i video.mp4 -ss 00:01:00 -to 00:02:00 cut.mp4 ``` 在這裡,第二個命令將直接從 `00:01:00` 至 `00:02:00` 分割出一個片段,而第一個命令將從輸入 `00:01:00` 至 `00:03:00` 分割出一個片段,因為 `00:01:00` 被歸零,所以原本 `00:03:00` 就變成了 `00:02:00`。 假如使用複製串流 `-c copy` 來建立分割,必須要使用 `-avoid_negative_ts 1` 選項,如果想要在 `concat` demuxer 上使用該分割的話。 例如: ```powershell ffmpeg -ss 00:03:00 -i video.mp4 -t 60 -c copy -avoid_negative_ts 1 cut.mp4 ``` ### 複製串流 使用 `-ss` 作為輸入選項 (位於 `-i` 之前) 並與 `-c:v copy` 一起使用則可能會不準確,因為 ffmpeg 被迫只能 使用 I畫格 (i-frames) 作為分割點。如果不複製視訊串流,而是重新編碼的話,無論 `-ss` 作為輸入或輸出選項則都能精準時間點。 如果 `-ss` 作為輸出選項 並與 `-c:v copy` 一起使用,則輸出可能會無法正常播放: ```powershell ffmpeg -i input.mkv -ss 00:02:00 -c copy output.mkv ``` 分割點可以準確在 `00:02:00`,但輸出片段可能無法正常播放,因為輸出的第一張畫格 (frame) 可能不是 I畫格 (i-frame)。所以如果分割點不是 I畫格 (i-frame),為了讓輸出能正常被解碼/播放,不能使用複製視訊的方法而必須改用重新編碼的方法來改變 GOP 結構。 ###### tags: `ffmpeg`