我想在尋找到某個位置後進行編碼,並且我想讓第一幀成為關鍵幀,這裡我使用的命令:
ffmpeg -ss 300 -i howimet.mp4 -acodec libfaac -ar 48000 -ab 128k -ac 2 -vcodec libx264 -vf "scale=480:270" -f mpegts -force_key_frames 300 -t 120 howimet2.ts
-force_key_frames 設定為尋找位置以在此建立關鍵影格。我使用以下腳本(來自這裡) 檢查第一幀是否為關鍵幀
ffprobe -show_frames -v quiet howimet2.ts | awk -F= ' /pict_type=/ { if (index($2, "I")) { i=1; } else { i=0; } }
/pkt_pts_time/ { if (i && ($2 >= 0)) print $2; }
' | head -n 1
結果顯示第一個關鍵影格不在第二個0處。
我想我的命令不正確。我缺什麼?
答案1
視訊編碼時,第一幀有成為關鍵影格。它將是第一個完全編碼的幀,後續幀可以使用它進行幀間預測。此外,在編碼視訊序列的開頭,您將有一個 H.264 存取單元,告訴解碼器刷新。
因此,無論您在做什麼:除非您只是複製位元流,否則您都會對影片進行重新編碼,並且您的第一幀必須是關鍵影格。
現在,無論出於何種原因,您的串流的開始時間都會有偏移。這意味著所有呈現時間戳記也會根據此偏移量進行移動。如果檢查輸出的頭部ffprobe -show_frames
,您會發現第 0 幀確實是關鍵幀,但具有不同的 PTS。
為了彌補這一點,您可以從所有 PTS 中減去開始時間。
答案2
如前所述,影片的第一幀必須是 I 幀。您的問題不是來自編碼(或複製,如果這是您的口味),而是來自解碼。在輸入之前加上 -ss 是不精確的,因此 ffmpeg 正在盡最大努力讓您到達您想要的位置。 Ffmpeg 傳遞了該位置,從而告訴您一個非零的第一個時間戳。
我建議在 -i 之後嘗試第二個 -ss 。沿著 -ss 299 -i 輸入 -ss 1 。
這表示轉到您想要的位置,然後在處理之前解碼 1 秒鐘。我不確定這是否能解決您的積分問題,但希望它能讓您朝著正確的方向前進。
需要指出的是,我不認為 force_key_frames 命令正在執行您認為的操作。如果它做了什麼,它很可能只是告訴它每 300 秒在輸出中添加一個關鍵幀,但這只是一個猜測。這意味著只有輸出的第一幀才是關鍵幀 (t=120)。
答案3
使用“-g”設定 GOP 大小
只是為了證明準確性,這裡有 1 秒的片段
ffmpeg -i in.mkv -g 30 -hls_time 1 -hls_list_size 0 index.m3u8
m3u8 的樣子如下:
#EXTM3U
#EXT-X-VERSION:3
#EXT-X-TARGETDURATION:2
#EXT-X-MEDIA-SEQUENCE:0
#EXTINF:1.001000,
index0.ts
#EXTINF:1.001000,
index1.ts
#EXTINF:1.001000,
index2.ts
#EXTINF:1.001000,
index3.ts
#EXTINF:1.001000,
index4.ts
#EXTINF:1.001000,
index5.ts
#EXTINF:1.001000,
index6.ts
#EXTINF:1.001000,
index7.ts
#EXTINF:1.001000,
index8.ts
#EXTINF:1.001000,
index9.ts
#EXTINF:1.001000,
index10.ts
#EXTINF:1.001000,
index11.ts
#EXTINF:1.001000,
index12.ts
#EXTINF:1.001000,
index13.ts
#EXTINF:1.001000,
....