Skip to content

TS 檔案合併教學:4 種 FFmpeg concat 方法比較

下載 HLS 串流得到的 TS 片段,需要合併成一個檔案。多個影片片段要連接成一個檔案。FFmpeg 提供 4 種 concat 方法,各有適用場景。這篇詳細比較這 4 種方法,幫你選擇適合的。

為什麼要合併 TS 檔案

  • HLS 下載後合併: M3U8 串流由多個 TS 片段組成,需要合併成單一 MP4
  • 攝影機片段整合: 長時間錄影分成多個檔案儲存
  • 剪輯片段連接: 多段素材要連接成一個完整影片
  • 直播錄製整合: 直播分段錄製要合併

4 種 FFmpeg concat 方法

方法 1:concat demuxer(推薦)

適用場景: 相同編碼器和參數的檔案

優點: 無損、最快、低資源使用

缺點: 所有檔案需要相同參數

使用方式

  1. 建立檔案清單 list.txt
file 'segment1.ts'
file 'segment2.ts'
file 'segment3.ts'
  1. 執行 FFmpeg:
bash
# 輸出 TS
ffmpeg -f concat -safe 0 -i list.txt -c copy output.ts

# 輸出 MP4
ffmpeg -f concat -safe 0 -i list.txt -c copy output.mp4

參數說明

  • -f concat:使用 concat demuxer
  • -safe 0:允許絕對路徑
  • -i list.txt:檔案清單
  • -c copy:串流複製(無損)

自動生成清單

bash
# Linux/macOS
for f in *.ts; do echo "file '$f'" >> list.txt; done

# Windows PowerShell
Get-ChildItem *.ts | ForEach-Object { Add-Content list.txt "file '$($_.Name)'" }

方法 2:concat protocol

適用場景: MPEG-TS 檔案直接合併

優點: 簡單

缺點: 只適用於 MPEG-TS,可能有相容性問題

使用方式

bash
# TS 檔案合併
ffmpeg -i "concat:segment1.ts|segment2.ts|segment3.ts" -c copy output.ts

# 輸出 MP4
ffmpeg -i "concat:segment1.ts|segment2.ts|segment3.ts" -c copy -bsf:a aac_adtstoasc output.mp4

注意: 只有 MPEG-TS 容器支援 concat protocol。MP4、MKV 等不支援。

方法 3:concat filter

適用場景: 不同編碼器或參數的檔案

優點: 支援不同參數

缺點: 重新編碼(有損)、慢

使用方式

bash
# 2 個檔案合併
ffmpeg -i input1.mp4 -i input2.mp4 -filter_complex \
  "[0:v:0][0:a:0][1:v:0][1:a:0]concat=n=2:v=1:a=1[outv][outa]" \
  -map "[outv]" -map "[outa]" output.mp4

# 3 個檔案合併
ffmpeg -i input1.mp4 -i input2.mp4 -i input3.mp4 -filter_complex \
  "[0:v:0][0:a:0][1:v:0][1:a:0][2:v:0][2:a:0]concat=n=3:v=1:a=1[outv][outa]" \
  -map "[outv]" -map "[outa]" output.mp4

參數說明

  • n=2:合併檔案數
  • v=1:輸出視訊串流
  • a=1:輸出音訊串流
  • [0:v:0][0:a:0]:第一個輸入的視訊和音訊

不同解析度合併

bash
# 統一解析度後合併
ffmpeg -i input1.mp4 -i input2.mp4 -filter_complex \
  "[0:v]scale=1280:720[v0];[1:v]scale=1280:720[v1];[v0][0:a][v1][1:a]concat=n=2:v=1:a=1[outv][outa]" \
  -map "[outv]" -map "[outa]" output.mp4

方法 4:中間檔案方法

適用場景: 不同容器但相同編碼器

優點: 支援不同容器

缺點: 需要額外儲存空間

使用方式

bash
# 步驟 1:MP4 轉 TS
ffmpeg -i input1.mp4 -c copy -bsf:v h264_mp4toannexb temp1.ts
ffmpeg -i input2.mp4 -c copy -bsf:v h264_mp4toannexb temp2.ts

# 步驟 2:用 concat protocol 合併
ffmpeg -i "concat:temp1.ts|temp2.ts" -c copy -bsf:a aac_adtstoasc output.mp4

# 步驟 3:刪除中間檔案
rm temp1.ts temp2.ts

方法比較

方法速度無損支援不同參數使用場景
concat demuxer最快相同參數
concat protocolTS 檔案
concat filter✗(重新編碼)不同參數
中間檔案不同容器

HLS 下載後 TS 合併

從 HLS 串流下載的 TS 片段合併:

bash
# 1. 下載 M3U8 列出的所有 TS 片段
ffmpeg -i "https://example.com/stream.m3u8" -c copy -bsf:a aac_adtstoasc output.mp4

# 2. 已經有 TS 檔案時用 concat demuxer 合併
for f in segment*.ts; do echo "file '$f'" >> list.txt; done
ffmpeg -f concat -safe 0 -i list.txt -c copy -bsf:a aac_adtstoasc output.mp4

-bsf:a aac_adtstoasc 把 AAC 從 ADTS 格式轉成 MP4 容器格式。

詳見 MP4 轉 M3U8 教學

常見問題

1. 合併後播放卡頓

原因: 時間戳衝突

解決方案:

bash
# 重新生成時間戳
ffmpeg -f concat -safe 0 -i list.txt -c copy -fflags +genpts output.mp4

2. 音訊不同步

原因: 音訊串流起始時間不同

解決方案:

bash
# 重置時間戳
ffmpeg -f concat -safe 0 -i list.txt -c copy -copyts -output_ts_offset 0 output.mp4

3. 部分檔案無法合併

原因: 編碼器或參數不同

解決方案: 用 concat filter 重新編碼

4. 合併後檔案巨大

原因: 串流複製保留原始位元率

解決方案: 合併後重新壓縮

bash
ffmpeg -f concat -safe 0 -i list.txt -c:v libx264 -crf 23 -c:a aac -b:a 128k output.mp4

進階技巧

1. 跳過損壞片段

bash
# 跳過損壞部分繼續處理
ffmpeg -f concat -safe 0 -i list.txt -c copy -err_detect ignore_err output.mp4

2. 部分合併

bash
# 只合併前 5 個檔案
head -5 list.txt > list-short.txt
ffmpeg -f concat -safe 0 -i list-short.txt -c copy output.mp4

3. 同時合併和轉換

bash
# 合併並轉成 H.265
ffmpeg -f concat -safe 0 -i list.txt -c:v libx265 -crf 28 -c:a aac -b:a 128k output.mp4

4. 加上過場效果

bash
# 場景間加 1 秒黑畫面
ffmpeg -i input1.mp4 -i input2.mp4 -filter_complex \
  "[0:v]format=yuv420p[v0];[1:v]format=yuv420p[v1];[v0][0:a][v1][1:a]concat=n=2:v=1:a=1[outv][outa]" \
  -map "[outv]" -map "[outa]" output.mp4

各場景範本

HLS 下載 TS 合併

bash
# 直接下載並合併
ffmpeg -i "https://example.com/stream.m3u8" -c copy -bsf:a aac_adtstoasc output.mp4

攝影機片段合併

bash
# 生成清單
for f in CAM*.ts; do echo "file '$f'" >> list.txt; done

# 無損合併
ffmpeg -f concat -safe 0 -i list.txt -c copy output.mp4

不同解析度片段合併

bash
# 統一解析度後合併
ffmpeg -i input1.mp4 -i input2.mp4 -filter_complex \
  "[0:v]scale=1920:1080[v0];[1:v]scale=1920:1080[v1];[v0][0:a][v1][1:a]concat=n=2:v=1:a=1[outv][outa]" \
  -map "[outv]" -map "[outa]" -c:v libx264 -crf 23 -c:a aac output.mp4

總結

TS 檔案合併方法選擇:

  • 相同參數: concat demuxer(推薦)
  • TS 檔案: concat protocol
  • 不同參數: concat filter
  • 不同容器: 中間檔案方法

快速參考:

  • 推薦方法: ffmpeg -f concat -safe 0 -i list.txt -c copy output.mp4
  • 不同參數: 用 concat filter
  • HLS 下載: ffmpeg -i stream.m3u8 -c copy output.mp4
  • TS→MP4:-bsf:a aac_adtstoasc

參考資料

Last updated: