[電腦] 電腦工具 / ffmpeg
===
###### tags: `學科`
###### tags: `學科`, `電腦`, `工具`, `ffmpeg`, `video`, `m3u8`, `mpd`, `m4s`, `mp4`, `剪接`, `剪輯`, `裁減`
<br>
[TOC]
<br>
## 教學
### 轉檔
- [[vob -> mp4] ffmpeg – 把光碟轉換成MP4](http://jashliao.eu/wordpress/2020/11/26/ffmpeg-%E6%8A%8A%E5%85%89%E7%A2%9F%E8%BD%89%E6%8F%9B%E6%88%90mp4/)
1. 合併多個 vob 文件
Linux: `$ cat *.VOB > output.vob`
Windows: `> copy *.VOB output.vob`
2. 識別vob 信息
`ffmpeg -i output.vob`
3. 進一步識別視頻信息
`$ ffmpeg -analyzeduration 100M -probesize 100M -i output.vob`
4. 轉檔
```
$ ffmpeg -i output.vob -preset superfast -crf 21 \
-c:a ac3 \
-c:s copy \
-map 0:1 -map 0:2 -map 0:3 -map 0:4 -map 0:5 \
output.mkv
```
速度和質量比較理想的平衡
`-preset superfast -crf 18`
### 參數
- ### [x264的preset與編碼速度、影片畫質以及位元率的關聯](https://magiclen.org/x264-preset/)
- ### [超簡單的中階影片轉檔教學](https://blog.xuite.net/ak47xd/blog/63836273)
C:CRF (Constant Rate Factor)
固定 質量/品質 係數
- 指定影片品質,無法預先得知位元率
- 數值0~51,可以是浮點數。數值越大檔案越小、畫質越差
- 接近無損:17、18
- 畫質良好:19~22
- 畫質好:23、24
- 不能看:>30
- ### [FFmpeg H.264 編碼器](https://blog.dexiang.me/zh-tw/technologies/ffmpeg-h264-options/)
- Constant Rate Factor(CRF)
- 固定品質指標,而不在意大小
- CRF 會得到最佳的 bitrate 分配結果
- 缺點是你不能直接指定一個目標 bitrate 或是檔案大小。
- 設定值範圍為 0 – 51
- 0 為最高品質
- 預設值為 23
- 建議的範圍在 18 - 28,17 或 18 接近視覺無損,
但在技術上來說並不是無損。
- Preset
用來設定編碼速度,相對的也會影響到壓縮比;編碼越快則壓縮比越低。
- 參數優先順序
preset -> tune -> "custom" -> profile -> level
- [X264碼率控制總結1——ABR,CQP,CRF](https://www.twblogs.net/a/5c9c055ebd9eee73ef4b130e)
- ### map
- [ffmpeg命令行map参数的使用](https://blog.csdn.net/xiaoluer/article/details/81136478) :+1: :100:
- 输出文件的stream顺序取决于在命令行中-map的参数顺序。
- 範例1
- input
```
Stream #0:0(eng): Video: h264 (High), ..
Stream #0:1(ger): Audio: dts (DTS), ...
Stream #0:2(eng): Audio: dts (DTS), ...
Stream #0:3(ger): Subtitle: text (default)
```
- target
- 将视频流复制
- 将德语音频流编码为MP3(128kbps)和AAC(96kbps)(在输出中创建两个音频流)
- 将英语音频流删除
- 将字幕流复制
- command
```bash=
$ ffmpeg -i input.mkv \
-map 0:0 -map 0:1 -map 0:1 -map 0:3 \
-c:v copy \
-c:a:0 libmp3lame -b:a:0 128k \
-c:a:1 libfaac -b:a:1 96k \
-c:s copy \
output.mkv
```
- 範例8
- input
`Stream #0:3[0x81]: Audio: ac3, 48000 Hz, 5.1(side), fltp, 448 kb/s`
- map 用法(同義)
- `-map 0:3`
- `-map i:0x81`
- ### mkv
> 須加上 `-fflags +genpts`
- [Timestamps are unset in a packet for stream 0. This is deprecated and will stop working in the future. Fix your code to set the timestamps properly](https://video.stackexchange.com/questions/24462)
- ### subtitle
- [[FFmpeg] 烙印字幕至影像上 (Hardsub)](https://www.mobile01.com/topicdetail.php?f=510&t=4462836)
- [How to extract subtitle from video using ffmpeg?](https://superuser.com/questions/583393)
### error 排解
- `Stream map '0:4' matches no streams.
To ignore this, add a trailing '?' to the map.`
- **原始指令**
`$ ffmpeg.exe -i VTS_05_1.VOB -c:a copy -c:s copy -map 0:1 -map 0:2 -map 0:3 -map 0:4 -map 0:5 VTS_05_1.mp4`
<br>
- **解決方法:**
添加參數
`-analyzeduration 100M -probesize 100M`
且要放在 `-i` 前面
`$ ffmpeg.exe -analyzeduration 100M -probesize 100M -i VTS_05_1.VOB`
字幕檔資訊,約出現在 30M 左右
[](https://i.imgur.com/QzcS35u.png)
- 在沒有 `-map 0:4 -map 0:5` 參數,隨後找到的資訊
<br>
- **完整指令**
`$ ffmpeg.exe -analyzeduration 100M -probesize 100M -i VTS_05_1.VOB -c:a copy -c:s copy -map 0:1 -map 0:2 -map 0:3 -map 0:4 -map 0:5 VTS_05_1.mp4`
- **參考說明**
- [ffmpeg: how to include a later starting dvb-subtitle stream?](https://askubuntu.com/questions/1105050)
> option `-probesize` to force ffmpeg to search enough bytes into the input file
> option `-analyzeduration` to force it to search for enough seconds.
- **注意**:底下兩者結果不同
- `$ ffmpeg.exe -analyzeduration 100M -probesize 100M -i VTS_05_1.VOB`
```
Input #0, mpeg, from 'VTS_05_1.VOB':
Duration: 00:23:30.88, start: 0.280633, bitrate: 6088 kb/s
Stream #0:0[0x1bf]: Data: dvd_nav_packet
Stream #0:1[0x1e0]: Video: mpeg2video (Main), yuv420p(tv, progressive), 720x480 [SAR 32:27 DAR 16:9], 30 fps, 59.94 tbr, 90k tbn, 59.94 tbc
Side data:
cpb: bitrate max/min/avg: 9000000/0/0 buffer size: 1835008 vbv_delay: N/A
Stream #0:2[0x80]: Audio: ac3, 48000 Hz, 5.1(side), fltp, 448 kb/s
Stream #0:3[0x81]: Audio: ac3, 48000 Hz, 5.1(side), fltp, 448 kb/s
Stream #0:4[0x21]: Subtitle: dvd_subtitle
Stream #0:5[0x20]: Subtitle: dvd_subtitle
```
- `$ ffmpeg.exe -i VTS_05_1.VOB -analyzeduration 100M -probesize 100M`
```
Input #0, mpeg, from 'VTS_05_1.VOB':
Duration: 00:23:30.88, start: 0.280633, bitrate: 6088 kb/s
Stream #0:0[0x1bf]: Data: dvd_nav_packet
Stream #0:1[0x1e0]: Video: mpeg2video (Main), yuv420p(tv, progressive), 720x480 [SAR 32:27 DAR 16:9], 30.47 fps, 59.94 tbr, 90k tbn, 59.94 tbc
Side data:
cpb: bitrate max/min/avg: 9000000/0/0 buffer size: 1835008 vbv_delay: N/A
Stream #0:2[0x80]: Audio: ac3, 48000 Hz, 5.1(side), fltp, 448 kb/s
Stream #0:3[0x81]: Audio: ac3, 48000 Hz, 5.1(side), fltp, 448 kb/s
```
### 參考資料
- ### [FFmpeg 簡易教學](https://lnpcd.blogspot.com/2012/09/ffmpeg.html)
- 映射功能
- 重新轉檔
- 切割影片
- 合併影片檔
- ### [利用ffmpeg指令影片轉檔與合併字幕](https://shimeche.github.io/2016/10/14/利用ffmpeg影片轉檔與合併字幕/)
<br>
<hr>
<br>
## 剪接/剪輯/裁減
- ### ffmpeg可以作影片裁減嗎? 比如指定第 0 - 10 秒輸出
> 使用 FFmpeg 裁減影片
FFmpeg 可以用來裁減影片的特定部分,使用 `-ss` 和 `-to` 參數即可完成。以下是一個範例,裁減影片第 0 到 10 秒:
### 範例指令
```
ffmpeg -i input.mp4 -ss 0 -to 10 -c copy output.mp4
```
### 參數說明
1. **`-i input.mp4`**:指定輸入的影片檔案。
2. **`-ss 0`**:設定起始時間為第 0 秒。
3. **`-to 10`**:設定結束時間為第 10 秒。
4. **`-c copy`**:直接複製編碼,不重新壓縮,處理速度更快,且保留原始畫質。
### 如果需要重新編碼
如果你需要重新編碼影片(例如改變格式或壓縮),可以省略 `-c copy`,如下:
```
ffmpeg -i input.mp4 -ss 0 -to 10 output.mp4
```
這樣的方式會重新壓縮影片,輸出檔案的大小和畫質可能會有所改變。
### 注意事項
- **更精確裁減**:如果需要更精確的時間裁減(到幀級),可以將 `-ss` 放在 `-i` 後面(如上述範例),這樣裁減會更精準。
- **測試片段**:若處理的檔案非常大,建議先測試小片段,確保參數正確,再對完整檔案操作。
---
- ### [排解問題] 為何轉檔完,前面的影格都沒有變換,直到數秒後,才能正常撥放?
> FFmpeg 剪裁影片問題與解決方案:
> - 不要使用 `-c copy`
> - 且需要重新編碼
> (2025/01/03 驗證過)
### 問題描述
當使用 FFmpeg 剪裁影片時,可能會出現影片的前幾秒未正常變換的情況,直到數秒後才正常播放。這通常是因為 `-ss` 參數的使用位置與解碼方式造成的。
### 問題原因
1. **`-ss` 放在輸入檔 (`-i`) 之前**
- 此時 FFmpeg 以「快速跳過幀」的方式定位到指定的時間點,但這種方式可能不夠精確。
- 如果指定的起始時間點不是關鍵幀(Keyframe),影片仍需解碼從最近的關鍵幀開始的所有幀,導致頭幾秒可能包含未裁減的畫面。
2. **關鍵幀問題**
- 關鍵幀是完整存儲畫面數據的幀,其餘幀依賴關鍵幀進行解碼。
- 若裁剪點不在關鍵幀上,FFmpeg 會包括從最近關鍵幀開始到指定時間點之間的畫面。
---
### 解決方法
1. **將 `-ss` 放在輸入檔 (`-i`) 後**
- 這樣 FFmpeg 會先解碼再定位,能更精確地裁減到指定的時間點:
```
ffmpeg -i input.mp4 -ss 0 -to 10 -c copy output.mp4
```
2. **使用重新編碼**
- 不使用 `-c copy`,讓 FFmpeg 重新編碼影片:
```
ffmpeg -i input.mp4 -ss 0 -to 10 output.mp4
```
- 雖然重新編碼耗時較長,但能確保裁減的畫面完全正確。
3. **結合快速定位與精確裁減**
- 使用 `-ss` 放在輸入之前快速跳到接近時間點,再進行精確裁減:
```
ffmpeg -ss 0 -i input.mp4 -to 10 output.mp4
```
### 推薦使用方法
- **快速方式**:
使用 `-c copy` 並將 `-ss` 放在輸入檔之前,處理速度快,但精度可能稍低。
- **精確方式**:
將 `-ss` 放在輸入檔之後,或直接重新編碼,能保證時間點精確。
### 注意事項
1. **快速剪裁與精確性**:
如果需要更精確的裁減結果,推薦重新編碼或將 `-ss` 放在輸入檔之後。
2. **處理大檔案**:
建議先測試小片段以確保參數正確,避免耗時處理整個檔案後才發現問題。
<br>
<hr>
<br>
## 轉檔
### mov to mp4
- [Convert .mov to .mp4 with ffmpeg](https://mrcoles.com/convert-mov-mp4-ffmpeg/)
```
ffmpeg -i input.mov -vcodec h264 -acodec mp2 output.mp4
```
- [Getting the smallest video with same quality, how to with FFMPEG?](https://superuser.com/questions/933264/)
```
ffmpeg -i input.avi -c:v libx264 -crf 18 -preset veryslow -c:a copy out.mp4
```
- -vcodec libx264 -crf 18
### mp4 to mkv
```
ffmpeg -i input.mp4 -c:v copy -crf 19 output.mkv
```
<br>
<hr>
<br>
### mp4 to mp3
- ### [How can I convert MP4 video to MP3 audio with FFmpeg?](https://superuser.com/questions/332347/)
```
ffmpeg -i filename.mp4 filename.mp3
```
or
```
ffmpeg -i video.mp4 -b:a 192K -vn music.mp3
```
<br>
### m3u8 to ts
- ### [利用ffmpeg合併m3u8串流影片,並且轉成MP4格式/](https://shimeche.github.io/2017/04/13/利用ffmpeg合併m3u8串流影片,並且轉成MP4格式/)
- 範例
`ffmpeg -i "m3u8網址" -c copy output.ts`
<br>
### m3u8 to mp4
- ### [利用ffmpeg合併m3u8串流影片,並且轉成MP4格式/](https://shimeche.github.io/2017/04/13/利用ffmpeg合併m3u8串流影片,並且轉成MP4格式/)
- 範例
`ffmpeg -i "m3u8網址" -c copy output.mp4`
- 網址最好用雙引號標示 (在 windows 可能有不如預期)
- -c copy 告知影音編碼用複製就好,不需要再次轉碼
- 透過 wget 下載 + cat 合併
- ### [[stackoverflow] Protocol 'https' not on whitelist](https://stackoverflow.com/questions/50455695)
- 參數用法
`-protocol_whitelist file,http,https,tcp,tls,crypto`
- 範例
```
ffmpeg \
-protocol_whitelist file,http,https,tcp,tls,crypto \
-i input.m3u8 \
-c copy \
output.mp4
```
<br>
<hr>
<br>
## 合併
- ### [How to merge audio and video file in ffmpeg](https://superuser.com/questions/277642)
```
ffmpeg -i video.mp4 -i audio.wav -c:v copy -c:a aac output.mp4
```
### [討論] 使用 ffmpeg 合併無音訊影片與音訊檔案
- ### Q: 我要執行 ffmpeg
```
- input: videoplayback.mp4 (no audio)
- input: videoplayback.m4a (audio)
- output: mp4 with audio
```
- ### gpt-4o
### 指令說明:
使用 `ffmpeg` 將影片 (`videoplayback.mp4`) 與音訊 (`videoplayback.m4a`) 合併成包含音訊的 MP4 檔案。
#### 指令:
```
ffmpeg -i videoplayback.mp4 \
-i videoplayback.m4a \
-c:v copy \
-c:a aac -b:a 192k \
output.mp4
```
#### 參數說明:
- `-i videoplayback.mp4`:指定影片輸入檔(無音訊)。
- `-i videoplayback.m4a`:指定音訊輸入檔。
- `-c:v copy`:保持影片編碼不變(直接複製,不重新編碼)。
- `-c:a aac -b:a 192k`:將音訊轉換為 AAC(如果 m4a 已經是 AAC,可省略重新編碼)。
- `output.mp4`:輸出的 MP4 檔案。
---
### 如果音訊檔 (`m4a`) 已經是 AAC 格式
如果 `videoplayback.m4a` 已經是 AAC 格式,可省略音訊轉碼,使用以下指令來直接複製音訊與影片:
```
ffmpeg -i videoplayback.mp4 \
-i videoplayback.m4a \
-c:v copy -c:a copy \
output.mp4
```
這樣可以避免重新編碼,提高處理速度並保持原始音訊品質。
<br>
<hr>
<br>
## 參數
### CRF (Constant Rate Factor)
> 固定 質量/品質 係數
- ### [超簡單的中階影片轉檔教學](https://blog.xuite.net/ak47xd/blog/63836273)
- 接近無損:17、18
- 畫質良好:19~22
- 畫質好:23、24
- 不能看:>30
<br>
### [討論] `-b:a 192k` 中的 `-b` 意思為何?全名為?
> b: bitrate
- ### gpt-4o
> FFmpeg `-b` 參數說明
`-b` 參數的全名是 **`-b:stream_specifier`**,代表 **比特率(bitrate)** 設定,適用於音訊與影片流。
在 `ffmpeg` 指令中:
```
ffmpeg -i videoplayback.mp4 \
-i videoplayback.m4a \
-c:v copy -c:a aac -b:a 192k \
output.mp4
```
- `-b:a` 是 `-b:audio` 的縮寫,代表 **設定音訊(audio)比特率**。
- `192k` 代表 **192 kbps(kilobits per second)**,即音訊的比特率為 192kbps。
## `-b` 的常見用法:
- `-b:v 3000k`:設定影片(video)比特率為 **3000kbps (3Mbps)**。
- `-b:a 128k`:設定音訊(audio)比特率為 **128kbps**。
在上述情境下,`-b:a 192k` 讓 ffmpeg 在轉換音訊時,使用 192kbps 作為 AAC 壓縮的比特率。
若省略 `-b:a`,ffmpeg 會使用編碼器的預設比特率。
<br>
<hr>
<br>
## 檔案類型
### .m3u8 (.ts list)
```
ffmpeg.exe -i "manifest.m3u8" -c copy output.mp4
```
- [由M3U8(TS)或MPD(M4S)获取视频](https://blog.csdn.net/jansenzhu/article/details/113785659)
<br>
### .mpd (.m4s list)
```
ffmpeg.exe -i "manifest.mpd" -c copy output.mp4
```
- [FFMPEG: How to manually select video quality from mpd manifest?](https://stackoverflow.com/questions/60549399)
```
$ ffprobe your_manifest.mpd
```
- [由M3U8(TS)或MPD(M4S)获取视频](https://blog.csdn.net/jansenzhu/article/details/113785659)
- mpd 有兩種類型:video 和 audio
- 得到视频和音频的*.mp4+*.m4s。但这时候的*.mp4是看不了的,因为它只是一个视频(音频)头
```
copy /b d:\video\1.mp4 d:\video\*.m4s video.mp4
```
- 最后用 ffmpeg 合并 video.mp4 和 audio.mp4
`ffmpeg.exe -i "d:\video\video.mp4" -i "d:\audio\audio.mp4" -c:v copy -c:a copy "D:\final.mp4"`
<br>
### m4s
- [如何无损合并video.m4s与audio.m4s为mp4文件](https://www.bilibili.com/read/cv10533506)
```
ffmpeg -i video.m4s -i audio.m4s -codec copy output.mp4
```
<br>
### .ts
> [wiki](https://zh.wikipedia.org/wiki/MPEG2-TS)
- merge
`copy /b *.ts merged.ts`
- File Type : M2T (MPEG-2 transport stream)
- MIME Type : video/mpeg
- Audio Stream Type : MPEG-2 AAC Audio
- 參考資料
- [利用ffmpeg合併m3u8串流影片,並且轉成MP4格式/](https://shimeche.github.io/2017/04/13/利用ffmpeg合併m3u8串流影片,並且轉成MP4格式/)
<br>
### .mp4
> [wiki](https://zh.wikipedia.org/wiki/MP4)
>
- File Type : MP4
- MIME Type : video/mp4
- Audio Stream Type : MP4 Base Media v1 [IS0 14496-12:2003]
- 參考資料
- [利用ffmpeg合併m3u8串流影片,並且轉成MP4格式/](https://shimeche.github.io/2017/04/13/利用ffmpeg合併m3u8串流影片,並且轉成MP4格式/)
{%hackmd vaaMgNRPS4KGJDSFG0ZE0w %}