Cách chính xác để sửa các khung hình chính trong FFmpeg cho DASH là gì?


38

Khi điều chỉnh một luồng để phát lại DASH, các điểm truy cập ngẫu nhiên phải ở cùng một thời gian luồng nguồn chính xác trong tất cả các luồng. Cách thông thường để làm điều này là buộc tốc độ khung hình cố định và độ dài GOP cố định (tức là khung hình chính trên mỗi khung hình N).

Trong FFmpeg, tốc độ khung hình cố định rất dễ dàng (-r SỐ).

Nhưng đối với các vị trí khung hình cố định (độ dài GOP), có ba phương thức ... phương pháp nào là "chính xác"? Tài liệu FFmpeg rất mơ hồ về điều này.

Phương pháp 1: gây rối với các đối số của libx264

-c:v libx264 -x264opts keyint=GOPSIZE:min-keyint=GOPSIZE:scenecut=-1

Dường như có một số tranh luận về việc có nên tắt cảnh sát hay không, vì không rõ liệu "bộ đếm" khung hình chính có được khởi động lại khi cắt cảnh xảy ra hay không.

Phương pháp 2: đặt kích thước GOP cố định:

-g GOP_LEN_IN_FRAMES

Thật không may, điều này chỉ được ghi lại trong tài liệu FFMPEG và do đó hiệu quả của lập luận này rất không rõ ràng.

Phương pháp 3: chèn một khung hình chính mỗi N giây ( Có thể? ):

-force_key_frames expr:gte(t,n_forced*GOP_LEN_IN_SECONDS)

Đây tài liệu rõ ràng. Nhưng vẫn chưa rõ ngay nếu "bộ đếm thời gian" khởi động lại sau mỗi khung hình chính. Chẳng hạn, trong GOP 5 giây dự kiến, nếu có một scenecutkhung hình chính được tiêm 3 giây vào libx264, thì khung hình tiếp theo sẽ là 5 giây sau hay 2 giây sau?

Trên thực tế, tài liệu FFmpeg phân biệt giữa -gtùy chọn này và tùy chọn, nhưng thực sự không nói hai tùy chọn trên ở trên khác nhau ít nhất như thế nào (rõ ràng -glà sẽ yêu cầu tốc độ khung hình cố định).

Cái nào đúng?

Có vẻ như nó -force_key_framessẽ vượt trội hơn , vì nó sẽ không yêu cầu tốc độ khung hình cố định. Tuy nhiên, điều này đòi hỏi rằng

  • nó phù hợp với thông số GOP trong H.264 ( nếu có )
  • Nó bảo đảm rằng sẽ có một khung hình chính trong nhịp cố định, không phân biệt các scenecutkhung hình chính libx264 .

Dường như -gcũng không thể hoạt động mà không buộc tốc độ khung hình cố định ( -r) , vì không có gì đảm bảo rằng nhiều lần chạy ffmpegvới các đối số codec khác nhau sẽ cung cấp cùng một tốc độ khung hình tức thời trong mỗi độ phân giải. Tốc độ khung hình cố định có thể làm giảm hiệu suất nén (QUAN TRỌNG trong kịch bản DASH!).

Cuối cùng, các keyintphương pháp chỉ có vẻ giống như một hack . Tôi hy vọng chống lại hy vọng rằng đây không phải là câu trả lời chính xác.

Tài liệu tham khảo:

Một ví dụ sử dụng -force_key_framesphương thức

Một ví dụ sử dụng keyintphương thức

Phần tùy chọn video nâng cao FFmpeg

Câu trả lời:


27

TL; DR

Tôi muốn giới thiệu như sau:

  • libx264: (và tùy chọn thêm )-g X -keyint_min X-force_key_frames "expr:gte(t,n_forced*N)"
  • libx265: -x265-params "keyint=X:min-keyint=X"
  • libvpx-vp9: -g X

trong đó Xkhoảng trong khung và Nlà khoảng thời gian tính bằng giây. Ví dụ: trong khoảng thời gian 2 giây với video 30 khung hình / giây, X= 60 và N= 2.

Một lưu ý về các loại khung khác nhau

Để giải thích chính xác chủ đề này, trước tiên chúng ta phải xác định hai loại I-frames / keyframes:

  • Các khung làm mới bộ giải mã tức thời (IDR): Chúng cho phép giải mã độc lập các khung sau mà không cần truy cập vào các khung trước khung IDR.
  • Các khung không phải IDR: Các khung này yêu cầu khung IDR trước đó để giải mã hoạt động. Các khung không phải IDR có thể được sử dụng để cắt cảnh ở giữa GOP (nhóm ảnh).

Những gì được đề nghị cho phát trực tuyến?

Đối với trường hợp phát trực tuyến, bạn muốn:

  • Đảm bảo rằng tất cả các khung IDR đều ở các vị trí thông thường (ví dụ: 2, 4, 6, giây giây) để video có thể được chia thành các phân đoạn có độ dài bằng nhau.
  • Cho phép phát hiện cắt cảnh, để cải thiện hiệu quả / chất lượng mã hóa. Điều này có nghĩa là cho phép các khung hình I được đặt ở giữa các khung IDR. Bạn vẫn có thể làm việc với tính năng phát hiện cắt cảnh bị vô hiệu hóa (và đây là một phần của nhiều hướng dẫn), nhưng không cần thiết.

Các tham số làm gì?

Để cấu hình bộ mã hóa, chúng ta phải hiểu các tham số keyframe làm gì. Tôi đã làm một số xét nghiệm và phát hiện ra những điều sau đây, trong ba bộ mã hóa libx264, libx265libvpx-vp9trong FFmpeg:

  • libx264:

    • -g đặt khoảng thời gian keyframe.
    • -keyint_min đặt khoảng thời gian keyframe tối thiểu.
    • -x264-params "keyint=x:min-keyint=y"cũng giống như -g x -keyint_min y.
    • Lưu ý: Khi đặt cả hai thành cùng một giá trị, mức tối thiểu được đặt bên trong thành một nửa khoảng thời gian tối đa cộng với một, như đã thấy trong x264mã:

      h->param.i_keyint_min = x264_clip3( h->param.i_keyint_min, 1, h->param.i_keyint_max/2+1 );
      
  • libx265:

    • -g không được thực hiện.
    • -x265-params "keyint=x:min-keyint=y" công trinh.
  • libvpx-vp9:

    • -g đặt khoảng thời gian keyframe.
    • -keyint_min đặt khoảng thời gian keyframe tối thiểu
    • Lưu ý: Do cách thức hoạt động của FFmpeg, -keyint_minchỉ được chuyển tiếp đến bộ mã hóa khi nó giống như -g. Trong mã từ libvpxenc.ctrong FFmpeg, chúng ta có thể tìm thấy:

      if (avctx->keyint_min >= 0 && avctx->keyint_min == avctx->gop_size)
          enccfg.kf_min_dist = avctx->keyint_min;
      if (avctx->gop_size >= 0)
          enccfg.kf_max_dist = avctx->gop_size;
      

      Đây có thể là một lỗi (hoặc thiếu tính năng?), Vì libvpxchắc chắn hỗ trợ thiết lập một giá trị khác cho kf_min_dist.

Bạn có nên sử dụng -force_key_frames?

Các -force_key_framestùy chọn ép chèn keyframe ở khoảng thời gian nhất định (biểu hiện). Điều này hoạt động cho tất cả các bộ mã hóa, nhưng nó có thể gây rối với cơ chế kiểm soát tốc độ. Đặc biệt đối với VP9, ​​tôi đã nhận thấy biến động chất lượng nghiêm trọng, vì vậy tôi không thể khuyên bạn nên sử dụng nó trong trường hợp này.


Cảm ơn bạn! Đây là phản hồi tuyệt vời. Một câu hỏi tôi có là làm thế nào bạn tạo ra bảng tuyệt vời đó. Tôi hoàn toàn có thể sử dụng một cái gì đó như thế.
Mark Gerolimatos

(Dường như không có cách nào để viết thư trực tiếp cho bạn) Bạn có thể vui lòng chỉ cho tôi các liên kết đến bất kỳ chủ đề nào trong cuộc thảo luận ITU-T này không? Cảm ơn!
Mark Gerolimatos

2
Tôi chỉ thực hiện điều đó trong Excel, dán đầu ra mà tôi nhận được từ ba lần chạy ffprobe -i input.mp4 -select_streams v -show_frames -of csv -show_entries frame=pict_type, sau đó tô màu các ô. Tôi sợ không có các cuộc thảo luận công khai, nhưng tôi sẽ xem liệu tôi có thể khai thác một số liên kết mà tôi tìm thấy sau đó không.
slhck

Bạn có thể vui lòng thử lại thử nghiệm của bạn với các -force_key_frames expr:gte(t,n_forced*GOP_LEN_IN_SECONDS)hình thức? Tôi vừa thử nó và thấy rằng trong khi có thêm khung hình I trong luồng, nó dường như tuân theo quy tắc của tôi. Một chương trình PERL sẽ theo sau như một "câu trả lời", vì rõ ràng bạn không thể sử dụng đánh dấu trong các bình luận.
Đánh dấu Gerolimatos

Hấp dẫn. Tôi tin rằng nó đáng giá một câu trả lời "thực sự" riêng biệt nếu bạn phát hiện ra rằng nó hoạt động. (Các trang web Stack Exchange không thực sự tốt cho câu trả lời kiểu thảo luận này.) Lần cuối cùng tôi kiểm tra, -force_key_framesnó không hoạt động với tôi và vì vậy tôi không bao giờ thử lại lần nữa. Đó là hơn một năm trước. Có lẽ đó là một lỗi. Tôi sẽ thử lại sớm.
slhck

12

Đây là năm mươi xu của tôi cho trường hợp.

Cách 1:

gây rối với các đối số của libx264

-c: v libx264 -x264opts keyint = GOPSIZE: min-keyint = GOPSIZE: perspectiveecut = -1

Tạo iframe chỉ trong khoảng thời gian mong muốn.

Ví dụ 1:

ffmpeg -i test.mp4 -codec:v libx264 \
-r 23.976 \
-x264opts "keyint=48:min-keyint=48:no-scenecut" \
-c:a copy \
-y test_keyint_48.mp4

Tạo iframe như mong đợi như thế này:

Iframes     Seconds
1           0
49          2
97          4
145         6
193         8
241         10
289         12
337         14
385         16
433         18
481         20
529         22
577         24
625         26
673         28
721         30
769         32
817         34
865         36
913         38
961         40
1009        42
1057        44
1105        46
1153        48
1201        50
1249        52
1297        54
1345        56
1393        58

Phương pháp 2 được khấu hao. Ommited.

Cách 3:

chèn một khung hình chính mỗi N giây (MAYBE):

-force_key_frames expr: gte (t, n_forced * GOP_LEN_IN_SECONDS)

Ví dụ 2

ffmpeg -i test.mp4 -codec:v libx264 \
-r 23.976 \
-force_key_frames "expr:gte(t,n_forced*2)"
-c:a copy \
-y test_fkf_2.mp4

Tạo một iframe theo một cách hơi khác:

Iframes     Seconds
1           0
49          2
97          4
145         6
193         8
241         10
289         12
337         14
385         16
433         18
481         20
519         21.58333333
529         22
577         24
625         26
673         28
721         30
769         32
817         34
865         36
913         38
931         38.75
941         39.16666667
961         40
1008        42
1056        44
1104        46
1152        48
1200        50
1248        52
1296        54
1305        54.375
1344        56
1367        56.95833333
1392        58
1430        59.58333333
1440        60
1475        61.45833333
1488        62
1536        64
1544        64.33333333
1584        66
1591        66.29166667
1632        68
1680        70
1728        72
1765        73.54166667
1776        74
1811        75.45833333
1824        75.95833333
1853        77.16666667
1872        77.95833333
1896        78.95833333
1920        79.95833333
1939        80.75
1968        81.95833333

Như bạn có thể thấy nó đặt iframe mỗi 2 giây VÀ trên phối cảnh (giây với phần nổi), điều này rất quan trọng đối với độ phức tạp của luồng video theo ý kiến ​​của tôi.

Kích thước tập tin genearated là khá giống nhau. Rất kỳ lạ là ngay cả với nhiều khung hình chính trong Phương thức 3 , đôi khi nó tạo ra ít tệp hơn thuật toán thư viện x264 tiêu chuẩn.

Để tạo nhiều tệp bitrate cho luồng HLS, chúng tôi chọn phương thức ba. Nó hoàn toàn phù hợp với 2 giây giữa các khối, chúng có iframe ở đầu mỗi đoạn và chúng có các iframe bổ sung cho các cảnh phức tạp mang lại trải nghiệm tốt hơn cho người dùng có thiết bị lỗi thời và không thể phát lại cấu hình cao x264.

Hy vọng nó sẽ giúp được ai đó.


Tuyệt vời, cảm ơn vì 50 xu của bạn!
BrunoFenzl

7

Câu trả lời do đó dường như là:

  • Phương pháp 1 được xác minh để hoạt động, nhưng là libx264cụ thể và có chi phí loại bỏ scenecuttùy chọn rất hữu ích trong libx264.
  • Phương pháp 3 hoạt động kể từ phiên bản FFMPEG của tháng 4 năm 2015, nhưng bạn nên xác minh kết quả của mình với tập lệnh được bao gồm ở cuối bài đăng này, vì tài liệu FFMPEG không rõ ràng về tác dụng của tùy chọn. Nếu nó hoạt động, nó là ưu việt của hai lựa chọn.
  • KHÔNG SỬ DỤNG Phương pháp 2, -gdường như không được dùng nữa. Nó dường như không hoạt động, cũng không được xác định rõ ràng trong tài liệu, cũng không được tìm thấy trong trợ giúp, và nó dường như không được sử dụng trong mã. Kiểm tra mã cho thấy -gtùy chọn này có khả năng dành cho các luồng MPEG-2 (thậm chí còn có các đoạn mã liên quan đến PAL và NTSC!).

Cũng thế:

  • Các tệp được tạo bằng Phương thức 3 có thể lớn hơn một chút so với Phương pháp 1, vì các khung I xen kẽ (khung hình chính) được cho phép.
  • Bạn nên đặt cờ "-r" một cách rõ ràng trong cả hai trường hợp, mặc dù Phương thức 3 đặt khung I ở khung hình tiếp theo vào hoặc sau thời gian được chỉ định. Việc không đặt cờ "-r" khiến bạn phải chịu trách nhiệm về tệp nguồn, có thể với tốc độ khung hình thay đổi. Chuyển đổi DASH không tương thích có thể dẫn đến.
  • Bất chấp các cảnh báo trong tài liệu FFMPEG, phương pháp 3 KHÔNG hiệu quả hơn các phương pháp khác. Trong thực tế, các thử nghiệm cho thấy rằng nó có thể hiệu quả hơn một chút so với phương pháp 1.

Kịch bản cho -force_key_framestùy chọn

Đây là một chương trình PERL ngắn mà tôi đã sử dụng để xác minh nhịp I-frame dựa trên đầu ra của đề xuất ffprobe của slhck. Dường như để xác minh rằng -force_key_framesphương thức này cũng sẽ hoạt động và có thêm lợi ích cho phép cho scenecutcác khung. Tôi hoàn toàn không biết làm thế nào FFMPEG làm cho công việc này hoạt động, hoặc nếu tôi chỉ may mắn bằng cách nào đó bởi vì các luồng của tôi xảy ra được điều hòa tốt.

Trong trường hợp của tôi, tôi đã mã hóa ở tốc độ 30 khung hình / giây với kích thước GOP dự kiến ​​là 6 giây hoặc 180 khung hình. Tôi đã sử dụng 180 làm đối số gopsize cho chương trình này để xác minh khung I ở mỗi bội số của 180, nhưng đặt nó thành 181 (hoặc bất kỳ số nào khác không phải là bội số của 180) khiến nó phàn nàn.

#!/usr/bin/perl
use strict;
my $gopsize = shift(@ARGV);
my $file = shift(@ARGV);
print "GOPSIZE = $gopsize\n";
my $linenum = 0;
my $expected = 0;
open my $pipe, "ffprobe -i $file -select_streams v -show_frames -of csv -show_entries frame=pict_type |"
        or die "Blah";
while (<$pipe>) {
  if ($linenum > $expected) {
    # Won't catch all the misses. But even one is good enough to fail.
    print "Missed IFrame at $expected\n";
    $expected = (int($linenum/$gopsize) + 1)*$gopsize;
  }
  if (m/,I\s*$/) {
    if ($linenum < $expected) {
      # Don't care term, just an extra I frame. Snore.
      #print "Free IFrame at $linenum\n";
    } else {
      #print "IFrame HIT at $expected\n";
      $expected += $gopsize;
    }
  }
  $linenum += 1;
}

Chỉ cần lưu ý: Vì đây là trang web Hỏi & Đáp và không thực sự là một diễn đàn thảo luận nơi các bài đăng được sắp xếp theo thứ tự thời gian, tốt nhất nên đặt tất cả thông tin vào một câu trả lời, để mọi người tìm kiếm giải pháp chỉ cần đọc một bài và không nhìn tại ai đã đăng những gì, khi nào :) Tôi đã hợp nhất câu trả lời của bạn và cũng cho bạn +1 về điều này. Vì đăng bài chéo không được phép , tôi khuyên bạn nên xóa câu hỏi của mình trên trang Video. Mọi người sẽ tìm thấy câu trả lời ở đây.
slhck

1
Tôi chỉ có một suy nghĩ nữa (thực ra nó đã được nêu ra trong danh sách gửi thư của FFmpeg). Khi bạn sử dụng force_key_frames, nó làm rối thuật toán phân bổ bit x264, do đó, nó có thể cung cấp cho bạn chất lượng kém hơn chỉ đơn giản là đặt khoảng thời gian khung hình cố định.
slhck

Thánh lồn Tuy nhiên, một lý do nữa để FFMPEG cung cấp một cách thức không mã hóa để thực hiện điều này, một đối số sẽ "làm điều tốt nhất cho codec trong câu hỏi". Tôi đã cố gắng đặt một vé cho điều này với trac của FFMPEG, nhưng bị trả lại :-(
Mark Gerolimatos

@slhck: Bạn có thể cho biết thêm chi tiết xin vui lòng? Tôi đã xem trong kho lưu trữ danh sách gửi thư vào tháng 5 năm 2015 nhưng không tìm thấy gì. Điểm mấu chốt là hãy quên đi "Phương pháp 3" và bám sát "Phương pháp 1".
schieferstapel

3
@MarkGerolimatos: về -g, bạn nói, "Nó dường như không hoạt động, ... cũng không xuất hiện để được sử dụng trong mã.". Tôi đã kiểm tra và đầu vào của gđược lưu trữ avctx->gop_sizevà libx264 sử dụng nó : x4->params.i_keyint_max = avctx->gop_size;. Khi tôi thăm dò tệp thử nghiệm được tạo này : ffmpeg -i a-test-file.mp4 -g 37 -t 15 gtest.mp4, tôi nhận được các khung hình chính xác 0,37,74,111,148,185,222,259,296,333,370. Một GOP có thể bị cắt ngắn nếu thay đổi cảnh được kích hoạt và đối với điều đó -sc_thresholdcó thể được đặt, cũng được chọn bởi x264.
Gyan ngày

4

Tôi muốn thêm một số thông tin ở đây vì việc tôi đã thảo luận khá nhiều trong cuộc tìm kiếm thông tin về việc cố gắng tìm cách phân đoạn mã hóa DASH của tôi theo cách tôi muốn và không có thông tin nào tôi tìm thấy là hoàn toàn chính xác.

Một số quan niệm sai lầm đầu tiên để thoát khỏi:

  1. Không phải tất cả các khung hình I đều giống nhau. Có các khung "I" lớn và các khung "i" nhỏ. Hoặc để sử dụng thuật ngữ chính xác, I-Frames IDR và ​​I-Frames không IDR. IDR I-frames (đôi khi được gọi là "khung hình chính") sẽ tạo GOP mới. Các khung không IDR sẽ không. Chúng rất tiện để có bên trong GOP nơi có sự thay đổi cảnh.

  2. -x264opts keyint=GOPSIZE:min-keyint=GOPSIZE← Điều này không làm những gì bạn nghĩ nó làm. Điều này làm tôi mất một chút thời gian để tìm ra. Hóa ra min-keyintlà giới hạn trong mã. Nó không được phép lớn hơn (keyint / 2) + 1. Vì vậy, việc gán cùng một giá trị cho hai biến này dẫn đến giá trị min-keyintbị giảm một nửa khi mã hóa.

Đây là điều: cắt cảnh thực sự tuyệt vời, đặc biệt là trong video có các đoạn cắt nhanh. Nó giữ cho nó đẹp và sắc nét, vì vậy tôi không muốn vô hiệu hóa nó, nhưng đồng thời tôi không thể có được kích thước GOP cố định miễn là nó được kích hoạt. Tôi muốn kích hoạt tính năng cắt cảnh, nhưng chỉ sử dụng I-frames không IDR. Nhưng nó không hoạt động. Cho đến khi tôi nhận ra (từ rất nhiều bài đọc) về quan niệm sai lầm # 2.

Hóa ra tôi cần keyintphải tăng gấp đôi kích thước GOP mong muốn của mình. Điều này có nghĩa là min-keyintcó thể được đặt thành kích thước GOP mong muốn của tôi (không có mã bên trong cắt một nửa), điều này ngăn phát hiện cắt cảnh sử dụng các khung I IDR bên trong kích thước GOP vì số khung hình kể từ Khung hình IDR cuối cùng là luôn nhỏ hơn min-keyinit.

Và cuối cùng thiết lập force_key_frametùy chọn ghi đè kích thước gấp đôi keyint. Vì vậy, đây là những gì hoạt động:

Tôi thích các phân đoạn trong 2 đoạn thứ hai, vì vậy GOPSIZE = Fram Cả * 2 của tôi

ffmpeg <other_options> -force_key_frames "expr:eq(mod(n,<GOPSIZE>),0)" -x264opts rc-lookahead=<GOPSIZE>:keyint=<GOPSIZE * 2>:min-keyint=<GOPSIZE> <other_options>

Bạn có thể xác minh bằng cách sử dụng ffprobe:

ffprobe <SRC_FLE> -select_streams v -show_frames -of csv -show_entries frame=coded_picture_number,key_frame,pict_type > frames.csv

Trong tệp CSV được tạo, mỗi dòng sẽ cho bạn biết frame, [is_an_IDR_?], [frame_type], [frame_number]::

frame,1,I,60  <-- frame 60, is I frame, 1 means is an IDR I-frame (aka KeyFrame)
frame,0,I,71  <-- frame 71, is I frame, 0 means not an IDR I_frame

Kết quả là bạn chỉ nên nhìn thấy I-Frames IDR theo các GOPSIZEkhoảng thời gian cố định , trong khi tất cả các khung I khác là các khung I-IDR không được chèn khi cần bằng cách phát hiện cắt cảnh.


đó là tuyệt vời! Đó là aldo rất phản trực giác, cảm ơn bạn đã nỗ lực. Và để tóm tắt, tôi giả sử định nghĩa của bạn về "I-frames" và "i-frames" là khái niệm (nghĩa là không thể cấu hình rõ ràng trong libx264), và "max * 2" có phải là cách bạn thực thi không?
Mark Gerolimatos

Vâng, đó chỉ là khái niệm, mặc dù tôi đã thấy mọi người sử dụng "I" so với "i" để phân biệt giữa các khung hình IDR và ​​không IDR. Và đúng vậy, đặt keyinit thành kích thước gop mong muốn * 2 là một cách để buộc tất cả các khung I bên trong gop không phải là các khung I-IDR. Sau đó, ffmpeg -force-key-frame over-rides key-init trong x264opts. Về cơ bản, đó là một cách thực sự lạc hậu để có được kết quả mong muốn có thể xảy ra nếu mã x264 cho phép bạn đặt min-keyinit và keyinit thành cùng một giá trị.
Reuben

... Trong khi cũng có thể bật phát hiện cắt cảnh và lấy kích thước GOP cố định.
Reuben

cảm ơn một lần nữa cho công việc tuyệt vời của bạn! Âm thanh như chúng ta cần một cách ít hiệu quả hơn "ngược"
Mark Gerolimatos

Là RC-lookahead cần thiết ở đây? Nó ảnh hưởng đến mbtree và VBV, nhưng nó có ảnh hưởng đến việc tạo khung i không?
Alexander Svetkin

0

Có vẻ như cú pháp này không hoạt động. Tôi đã kiểm tra khá nhiều về nội dung VOD của chúng tôi cũng như nội dung trực tiếp (kết xuất tệp) và đôi khi phối cảnh không hoạt động và kích hoạt một iframe giữa:

Cú pháp cho một upconvertion i50-> p50, 2 giây gop / phân đoạn, IDR khi bắt đầu, iframes xen giữa nếu cần

ffmpeg.exe -loglevel verbose -i avc_50i.ts -pix_fmt yuv420p -filter_complex yadif=1,scale=1920:1080 -vcodec libx264 -preset fast -x264-params "rc-lookahead=100:keyint=200:min-keyint=100:hrd=1:vbv_maxrate=12000:vbv_bufsize=12000:no-open-gop=1" -r 50 -crf 22 -force_key_frames "expr:eq(mod(n,100),0)" -codec:a aac -b:a 128k -y target.ts

0

Twitch có một bài về điều này. Họ giải thích rằng họ quyết định sử dụng chương trình của riêng họ vì nhiều lý do; Một trong số đó là ffmpeg không cho phép bạn chạy các phiên bản x264 khác nhau trong các luồng khác nhau, mà thay vào đó dành tất cả các luồng được chỉ định cho một khung hình trong một đầu ra trước khi chuyển sang đầu ra tiếp theo.

Nếu bạn không thực hiện phát trực tuyến thời gian thực, bạn có nhiều thứ xa xỉ hơn. Cách 'chính xác' có lẽ là mã hóa ở một độ phân giải chỉ với kích thước GOP được chỉ định bằng -g, sau đó mã hóa các độ phân giải khác buộc các khung hình chính ở cùng một vị trí.

Nếu bạn muốn làm điều đó, bạn có thể sử dụng ffprobe để lấy thời gian keyframe và sau đó sử dụng tập lệnh shell hoặc ngôn ngữ lập trình thực tế để chuyển đổi nó thành lệnh ffmpeg.

Nhưng đối với hầu hết các nội dung, có rất ít sự khác biệt giữa việc có một khung hình chính cứ sau 5 giây và hai khung hình chính cứ sau 5 giây (một bắt buộc và một từ phối cảnh). Đây là về kích thước khung I trung bình so với kích thước của khung P và khung B. Nếu bạn sử dụng x264 với các cài đặt thông thường (lý do duy nhất tôi nghĩ bạn nên làm bất cứ điều gì để ảnh hưởng đến những điều này là nếu bạn đặt -qmin, như một cách kém để ngăn x264 sử dụng bitrate trên nội dung dễ dàng; điều này giới hạn tất cả các loại khung có cùng giá trị , Tôi nghĩ vậy) và nhận được kết quả như kích thước trung bình của khung hình I là 46 kB, khung hình P 24 kB, khung hình B 17 kB (thường bằng một nửa khung hình P), sau đó thêm khung hình I mỗi giây ở 30 khung hình / giây chỉ tăng 3% kích thước tập tin. Sự khác biệt giữa h264 và h263 có thể được tạo thành từ một loạt giảm 3%, nhưng một điều duy nhất không quan trọng lắm.

Trên các loại nội dung khác, kích thước khung hình sẽ khác nhau. Công bằng mà nói, đây là về sự phức tạp theo thời gian chứ không phải sự phức tạp về không gian, vì vậy nó không chỉ là nội dung dễ dàng so với nội dung cứng. Nhưng nhìn chung, các trang web phát video trực tuyến có giới hạn bitrate và nội dung có khung I tương đối lớn là nội dung dễ dàng sẽ được mã hóa với chất lượng cao cho dù có thêm bao nhiêu khung hình chính. Thật lãng phí, nhưng chất thải này thường sẽ không được chú ý. Trường hợp lãng phí nhất có lẽ là một video chỉ là một hình ảnh tĩnh kèm theo một bài hát, trong đó mỗi khung hình chính xác giống nhau.

Một điều tôi không chắc chắn là làm thế nào các khung hình chính bắt buộc tương tác với bộ giới hạn tốc độ được đặt với -maxrate và -bufsize. Tôi nghĩ ngay cả YouTube cũng gặp sự cố gần đây khi định cấu hình chính xác cài đặt bộ đệm để có chất lượng ổn định. Nếu một số trang web chỉ sử dụng cài đặt bitrate trung bình mà một số trang web có thể nhìn thấy (vì bạn có thể kiểm tra các tùy chọn của x264 trong phần tử tiêu đề / Mov? Với trình soạn thảo hex) thì mô hình bộ đệm không phải là vấn đề, nhưng nếu bạn phục vụ nội dung do người dùng tạo, tốc độ bit trung bình khuyến khích người dùng thêm màn hình đen vào cuối video.

Tùy chọn -g của Ffmpeg hoặc bất kỳ tùy chọn bộ mã hóa nào khác mà bạn sử dụng được ánh xạ tới tùy chọn dành riêng cho bộ mã hóa. Vì vậy, '-x264-params keyint = GOPSIZE' tương đương với '-g GOPSIZE'.

Một vấn đề với việc sử dụng phát hiện cảnh là nếu bạn thích khung hình chính gần số cụ thể vì bất kỳ lý do gì. Nếu bạn chỉ định khung hình chính cứ sau 5 giây và sử dụng phát hiện cảnh và có thay đổi cảnh ở mức 4,5, thì nó sẽ được phát hiện, nhưng sau đó khung hình chính tiếp theo sẽ ở mức 9,5. Nếu thời gian cứ tiếp tục tăng dần như thế này, bạn có thể kết thúc với các khung hình chính ở 42,5, 47,5, 52,5, v.v., thay vì 40, 45, 50, 55. Ngược lại, nếu có thay đổi cảnh ở 5.5, thì sẽ có một khung hình chính ở mức 5 và 5,5 sẽ là quá sớm đối với một cái khác. Ffmpeg không cho phép bạn chỉ định "tạo khung hình chính ở đây nếu không có thay đổi cảnh trong 30 khung hình tiếp theo". Một người hiểu C có thể thêm tùy chọn đó, mặc dù.

Đối với video tốc độ khung hình thay đổi, khi bạn không phát trực tiếp như Twitch, bạn sẽ có thể sử dụng các thay đổi cảnh mà không cần chuyển đổi vĩnh viễn sang tốc độ khung hình không đổi. Nếu bạn sử dụng bộ lọc 'select' trong ffmpeg và sử dụng hằng số 'cảnh' trong biểu thức, thì đầu ra gỡ lỗi (-v gỡ lỗi hoặc nhấn '+' vài lần trong khi mã hóa) hiển thị số thay đổi cảnh. Điều này có lẽ khác với và không hữu ích bằng số được sử dụng bởi x264, nhưng nó vẫn có thể hữu ích.

Sau đó, quy trình có thể là thực hiện một video thử nghiệm chỉ dành cho thay đổi khung hình chính, nhưng có thể có thể được sử dụng cho dữ liệu kiểm soát tốc độ nếu sử dụng 2-pass. (Không chắc liệu dữ liệu được tạo có hữu ích cho các độ phân giải và cài đặt khác nhau hay không; dữ liệu cây macroblock sẽ không.) Chuyển đổi nó thành video tốc độ khung hình liên tục, nhưng hãy xem lỗi này về đầu ra bị gián đoạn khi giảm một nửa tốc độ khung hình nếu bạn quyết định để sử dụng bộ lọc fps cho các mục đích khác. Chạy nó qua x264 với các cài đặt keyframe và GOP mong muốn của bạn.

Sau đó, chỉ cần sử dụng các thời gian khung hình chính này với video tốc độ khung hình biến ban đầu.

Nếu bạn cho phép hoàn toàn điên cuồng nội dung do người dùng tạo với khoảng cách 20 giây giữa các khung, thì đối với mã hóa tốc độ khung hình thay đổi, bạn có thể tách đầu ra, sử dụng bộ lọc fps, bằng cách nào đó sử dụng bộ lọc chọn (có thể xây dựng biểu thức thực sự dài mỗi thời gian khung hình chính) ... hoặc có thể bạn có thể sử dụng video thử nghiệm làm đầu vào và chỉ giải mã các khung hình chính, nếu tùy chọn ffmpeg đó hoạt động hoặc sử dụng bộ lọc chọn để chọn khung hình chính. Sau đó chia tỷ lệ thành kích thước chính xác (thậm chí còn có bộ lọc scale2ref cho điều này) và phủ lên video gốc trên đó. Sau đó, sử dụng bộ lọc xen kẽ để kết hợp các khung hình chính bắt buộc này với video gốc. Nếu điều này dẫn đến hai khung hình cách nhau 0,001 giây mà bộ lọc xen kẽ không ngăn được, thì hãy tự giải quyết vấn đề này bằng một bộ lọc chọn khác. Xử lý các giới hạn bộ đệm khung cho bộ lọc xen kẽ có thể là vấn đề chính ở đây. Tất cả đều có thể hoạt động: sử dụng một số loại bộ lọc để đệm luồng dày đặc hơn (bộ lọc fifo?); tham khảo tệp đầu vào nhiều lần để nó được giải mã nhiều lần và các khung không phải được lưu trữ; sử dụng bộ lọc 'streamelect', điều mà tôi chưa bao giờ thực hiện, vào thời điểm chính xác của các khung hình chính; cải thiện bộ lọc xen kẽ bằng cách thay đổi hành vi mặc định của nó hoặc thêm tùy chọn để xuất khung cũ nhất trong bộ đệm thay vì bỏ khung. điều mà tôi chưa bao giờ thực hiện, vào thời điểm chính xác của các khung hình chính; cải thiện bộ lọc xen kẽ bằng cách thay đổi hành vi mặc định của nó hoặc thêm tùy chọn để xuất khung cũ nhất trong bộ đệm thay vì bỏ khung. điều mà tôi chưa bao giờ thực hiện, vào thời điểm chính xác của các khung hình chính; cải thiện bộ lọc xen kẽ bằng cách thay đổi hành vi mặc định của nó hoặc thêm tùy chọn để xuất khung cũ nhất trong bộ đệm thay vì bỏ khung.

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.