Làm cách nào để có được dấu thời gian của khung hình chính gần nhất trước dấu thời gian nhất định với FFmpeg?


17

Tôi muốn một lệnh tìm kiếm FFmpeg nhanh và chính xác. Tôi tìm thấy này .

Giải pháp là chúng tôi áp dụng -sscho cả đầu vào (tìm kiếm nhanh) và đầu ra (tìm kiếm chính xác). Nhưng: Nếu tìm kiếm đầu vào không chính xác, làm thế nào chúng ta có thể chắc chắn rằng vị trí tìm kiếm là chính xác?


Ví dụ: Nếu chúng tôi muốn tìm đến 00:03:00, lệnh này có dạng như sau:

ffmpeg -ss 00:02:30 -i <INPUT> ... -ss 00:00:30 <OUTPUT>

Người đầu tiên -sssẽ tìm đến một nơi khác, không 00:02:30, nói 00:02:31. Và sau khi áp dụng tìm kiếm thứ hai, kết quả cuối cùng sẽ là 00:03:01- không phải những gì chúng ta muốn. Đúng không?

Người đầu tiên -sstìm đến đâu? Nó có tìm đến keyframe gần nhất 00:02:30không?

Nếu vậy, đây là tôi suy nghĩ chính xác cho tôi nếu tôi sai: sau khi tìm kiếm đầu tiên, chúng tôi nhận được dấu thời gian của kết quả (trong ví dụ này: 00:02:31), sau đó chúng tôi áp dụng thứ hai tìm kiếm với thời gian thích hợp, trong trường hợp này 00:00:29.

Câu hỏi là: Làm thế nào để chúng ta có được dấu thời gian của kết quả tìm kiếm đầu tiên?

Câu trả lời:


18

Để trả lời theo nghĩa đen câu hỏi của bạn: Bạn có thể nhận danh sách các khung hình I với

ffprobe -select_streams v -show_frames <INPUT> 

Bạn có thể tiếp tục giới hạn điều này với đầu ra cần thiết bằng cách thêm -show_entries frame=pkt_pts_time,pict_type.

Để xem khung hình nào gần nhất (đến sau) một dấu thời gian nhất định, trước tiên bạn cần tìm hiểu tất cả các dấu thời gian của khung hình chính, ví dụ như với awk.

Đầu tiên, xác định thời gian bạn muốn tìm, ví dụ: 2: 30m tương đương với 150 giây.

ffprobe -select_streams v -show_frames -show_entries frame=pkt_pts_time,pict_type -v quiet in.mp4 | 
awk -F= ' 
  /pict_type=/ { if (index($2, "I")) { i=1; } else { i=0; } } 
  /pkt_pts_time/ { if (i && ($2 >= 150)) print $2; }  
' | head -n 1

Ví dụ, điều này sẽ trở lại 150.400000.


Lưu ý rằng khi sử dụng -sstrước đó -i, FFmpeg sẽ định vị khung hình chính trước điểm tìm kiếm, sau đó gán giá trị PTS âm cho tất cả các khung sau cho đến khi đạt đến điểm tìm kiếm. Người chơi nên giải mã nhưng không hiển thị các khung có PTS âm và video sẽ bắt đầu chính xác.

Một số người chơi không tôn trọng chính xác điều này và sẽ hiển thị video đen hoặc rác. Trong trường hợp này, tập lệnh trên có thể được sử dụng để tìm PTS của khung hình chính sau điểm tìm kiếm của bạn và sử dụng tập lệnh đó để bắt đầu tìm kiếm từ khung hình chính. Điều này, tuy nhiên, sẽ không chính xác.

Lưu ý rằng nếu bạn muốn siêu chính xác trong khi tìm kiếm và duy trì khả năng tương thích với nhiều người chơi, bạn có thể chuyển đổi video thành bất kỳ định dạng không mất dữ liệu nào, trong đó bạn có thể cắt bất cứ lúc nào, sau đó mã hóa lại. Nhưng điều này sẽ không nhanh.


1
cảm ơn, tôi không làm trình chỉnh sửa video, nhưng tôi muốn tìm kiếm video chính xác trong đó khoảng cách chỉ dưới 0,5 giây.
jackode

1
Bạn có thể có thể tung hứng với PTS từ ffprobe. Nếu không, bất kỳ định dạng trung gian nào cũng được, ví dụ như ProRes 422, DNxHD, chỉ mất trực quan và chỉ trong khung. Hoặc bạn sử dụng một cái gì đó như HuffYUV, vv Nhưng tất nhiên sau đó bạn sẽ mất khía cạnh "nhanh".
slhck

Phiên bản nào của ffprobe bạn đã sử dụng cho lệnh, bởi vì tôi đã nóiUnrecognized option 'select_streams'
jackode

2
Bạn đã đóng, select_streamstùy chọn đã được thêm vào tháng 10 năm 2012 . :) Bạn có thể làm mà không cần điều đó nhưng sau đó bạn cũng sẽ nhận được thông tin cho các khung âm thanh, xen lẫn vào giữa.
slhck

2
Lưu ý bạn có thể thêm dòng này các ffmpeg để cho nó chỉ ra 2 trường cần thiết, thay vì rất nhiều thứ mà bị vứt bỏ bởi awk: -show_entries khung = pkt_pts_time, pict_type
Jannes

6

Tôi hiểu câu hỏi này đã vài năm tuổi, nhưng phiên bản mới nhất của ffprobe có khả năng bỏ qua các khung . Bạn chỉ có thể chuyển -skip_frame nokeyđến báo cáo thông tin trên các khung chính (I-frames). Điều này có thể giúp bạn tiết kiệm rất nhiều thời gian! Trên tệp MP4 2GB 1080p, nó được sử dụng để mất 4 phút mà không bỏ qua các khung. Thêm thông số bỏ qua chỉ mất 20 giây.

Chỉ huy:

ffprobe -select_streams v -skip_frame nokey -show_frames -show_entries frame = pkt_pts_time, fig_type D: \ test.mp4

Các kết quả:

[FRAME]
pkt_pts_time=0.000000
pict_type=I
[/FRAME]
[FRAME]
pkt_pts_time=3.753750
pict_type=I
[/FRAME]
[FRAME]
pkt_pts_time=7.507500
pict_type=I
[/FRAME]
[FRAME]
pkt_pts_time=11.261250
pict_type=I
[/FRAME]
[FRAME]
pkt_pts_time=15.015000
pict_type=I
[/FRAME]

Vì vậy, kết quả sẽ chỉ chứa thông tin liên quan đến các khung chính.


0

nếu bạn muốn lấy thông tin của các khung I, bạn có thể sử dụng

ffprobe -i input.mp4 -v quiet -select_streams v -show_entries frame=pkt_pts_time,pict_type|grep -B 1 'pict_type=I'
Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.