DASH के लिए FFmpeg में कीफ्रेम को ठीक करने का सही तरीका क्या है?


38

जब DASH प्लेबैक के लिए एक स्ट्रीम कंडीशनिंग, यादृच्छिक अभिगम बिंदु सभी धाराओं में सटीक एक ही स्रोत स्ट्रीम समय पर होना चाहिए। ऐसा करने का सामान्य तरीका एक निश्चित फ्रेम दर और निश्चित जीओपी लंबाई (यानी हर एन फ्रेम की एक कुंजीपट) को बाध्य करना है।

FFmpeg में, निश्चित फ्रेम दर आसान है (-r NUMBER)।

लेकिन निश्चित कीफ़ोम स्थानों (जीओपी लंबाई) के लिए, तीन तरीके हैं ... कौन सा "सही" है? इस पर FFmpeg प्रलेखन निराशाजनक रूप से अस्पष्ट है।

विधि 1: libx264 के तर्कों के साथ खिलवाड़ करना

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

ऐसा प्रतीत होता है कि कुछ बहस हो रही है कि क्या दर्शनीय स्थलों को बंद कर दिया जाना चाहिए या नहीं, क्योंकि यह स्पष्ट नहीं है कि जब दृश्य कट होता है, तो कीफ्रेम "काउंटर" को फिर से शुरू किया जाता है।

विधि 2: एक निश्चित GOP आकार सेट करना:

-g GOP_LEN_IN_FRAMES

यह दुर्भाग्य से केवल एफएफएमपीईजी दस्तावेज में पारित होने का दस्तावेज है, और इस प्रकार इस तर्क का प्रभाव बहुत अस्पष्ट है।

विधि 3: हर N सेकंड ( शायद? ) के लिए एक कीफ़्रेम डालें :

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

यह है स्पष्ट रूप से प्रलेखित। लेकिन यह अभी भी स्पष्ट नहीं है अगर "टाइम काउंटर" हर कुंजी फ्रेम के बाद फिर से शुरू होता है। उदाहरण के लिए, एक अपेक्षित 5-सेकंड GOP में, यदि scenecutlibx264 द्वारा 3 सेकंड में एक कीफ़्रेम इंजेक्ट किया जाता है, तो क्या अगला कीफ़्रेम 5 सेकंड बाद या 2 सेकंड बाद होगा?

वास्तव में, FFmpeg प्रलेखन इस और -gविकल्प के बीच अंतर करता है, लेकिन यह वास्तव में यह नहीं कहता है कि ऊपर दिए गए ये दो विकल्प कैसे कम से कम थोड़ा अलग हैं (जाहिर है, -gएक निश्चित फ्रेम दर की आवश्यकता है)।

कौन सा सही है?

ऐसा लगता है कि यह -force_key_framesबेहतर होगा , क्योंकि इसमें निश्चित फ्रेम दर की आवश्यकता नहीं होगी। हालाँकि, इसके लिए यह आवश्यक है

  • यह H.264 में GOP विनिर्देशों के अनुरूप है ( यदि कोई हो )
  • यह गारंटी देता है कि निश्चित ताल में एक कीफ़्रेम होगा, भले ही libx264 scenecutकीफ़्रेम के बावजूद ।

यह भी प्रतीत होता है कि -gएक निश्चित फ्रेम दर ( -r) को मजबूर किए बिना काम नहीं कर सकता है , क्योंकि इसमें कोई गारंटी नहीं है कि ffmpegविभिन्न कोडेक तर्क के साथ कई रन प्रत्येक रिज़ॉल्यूशन में समान तात्कालिक फ्रेम दर प्रदान करेंगे। फिक्स्ड फ्रेम दरें संपीड़न प्रदर्शन को कम कर सकती हैं (एक डैश परिदृश्य में महत्वपूर्ण!)।

अंत में, विधि सिर्फ एक हैक की तरह लगता है । मुझे उम्मीद है कि यह सही उत्तर नहीं है।keyint

संदर्भ:

-force_key_framesविधि का उपयोग करके एक उदाहरण

keyintविधि का उपयोग करके एक उदाहरण

FFmpeg उन्नत वीडियो विकल्प अनुभाग

जवाबों:


27

टी एल; डॉ

मैं निम्नलिखित की सिफारिश करूंगा:

  • libx264: -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

Xफ़्रेम में अंतराल कहाँ है और Nसेकंड में अंतराल है। उदाहरण के लिए, 30fps वीडियो के साथ 2-सेकंड के अंतराल के लिए,X = 60 और N= 2।

विभिन्न फ्रेम प्रकारों के बारे में एक नोट

इस विषय को ठीक से समझाने के लिए, हमें सबसे पहले दो प्रकार के I- फ्रेम / कीफ्रेम को परिभाषित करना होगा:

  • तात्कालिक विकोडक रीफ़्रेश (IDR) फ़्रेम: ये IDR फ़्रेम के पिछले फ़्रेम तक पहुँच के बिना, निम्न फ़्रेम के स्वतंत्र डिकोडिंग की अनुमति देते हैं।
  • गैर-आईडीआर-फ्रेम: काम करने के लिए डिकोडिंग के लिए पिछले आईडीआर फ्रेम की आवश्यकता होती है। गैर-आईडीआर फ्रेम का उपयोग जीओपी (चित्रों के समूह) के बीच में दृश्य कटौती के लिए किया जा सकता है।

स्ट्रीमिंग के लिए क्या अनुशंसित है?

स्ट्रीमिंग मामले के लिए, आप चाहते हैं:

  • सुनिश्चित करें कि सभी IDR फ्रेम नियमित स्थिति पर हैं (उदाहरण 2, 4, 6,… सेकंड पर) ताकि वीडियो को समान लंबाई के खंडों में विभाजित किया जा सके।
  • दृश्य कट डिटेक्शन सक्षम करें, ताकि कोडिंग दक्षता / गुणवत्ता में सुधार हो सके। इसका मतलब है कि आई-फ्रेम को आईडीआर फ्रेम के बीच रखने की अनुमति देता है। आप अभी भी दृश्य कट डिटेक्शन अक्षम के साथ काम कर सकते हैं (और यह कई गाइडों का हिस्सा है, अभी भी), लेकिन यह आवश्यक नहीं है।

पैरामीटर क्या करते हैं?

एनकोडर को कॉन्फ़िगर करने के लिए, हमें यह समझना होगा कि कीफ्रेम पैरामीटर क्या करते हैं। मैंने कुछ परीक्षण किए और निम्नलिखित की खोज की, तीन एनकोडर के लिए libx264, libx265और libvpx-vp9FFmpeg में:

  • libx264:

    • -g कीफ़्रेम अंतराल सेट करता है।
    • -keyint_min न्यूनतम कीफ़्रेम अंतराल सेट करता है।
    • -x264-params "keyint=x:min-keyint=y"के रूप में ही है -g x -keyint_min y
    • नोट: दोनों को एक ही मान पर सेट करते समय, न्यूनतम आंतरिक रूप से अधिकतम अंतराल के आधे से एक सेट होता है , जैसा कि x264कोड में देखा गया है :

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

    • -g लागू नहीं है।
    • -x265-params "keyint=x:min-keyint=y" काम करता है।
  • libvpx-vp9:

    • -g कीफ़्रेम अंतराल सेट करता है।
    • -keyint_min न्यूनतम कीफ़्रेम अंतराल सेट करता है
    • नोट: एफएफएमपीई कैसे काम करता है, इसके -keyint_minकारण केवल एनकोडर को अग्रेषित किया जाता है जब यह उसी तरह होता है -glibvpxenc.cFFmpeg से कोड में हम पा सकते हैं:

      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;
      

      यह बग (या सुविधा की कमी?) हो सकता है, क्योंकि libvpxनिश्चित रूप से इसके लिए एक अलग मान सेट करने का समर्थन करता है kf_min_dist

क्या आपको उपयोग करना चाहिए -force_key_frames?

-force_key_framesविकल्प जबरन दिए गए अंतराल (अभिव्यक्ति) पर मुख्य-फ़्रेम सम्मिलित करता है। यह सभी एन्कोडर के लिए काम करता है, लेकिन यह दर नियंत्रण तंत्र के साथ खिलवाड़ कर सकता है। विशेष रूप से वीपी 9 के लिए, मैंने गंभीर गुणवत्ता में उतार-चढ़ाव देखा है, इसलिए मैं इस मामले में इसका उपयोग करने की अनुशंसा नहीं कर सकता।


धन्यवाद! यह शानदार प्रतिक्रिया है। एक प्रश्न मेरे पास है कि आपने उस भयानक तालिका को कैसे उत्पन्न किया। मैं पूरी तरह से कुछ का उपयोग कर सकता है।
मार्क गेरोलिमेटोस

(आपको सीधे लिखने का कोई तरीका नहीं प्रतीत होता) क्या आप मुझे इस ITU-T चर्चा में किसी सूत्र के लिंक की ओर इंगित कर सकते हैं? धन्यवाद!
मार्क गेरोलिमैटोस

2
मैंने सिर्फ एक्सेल में, तीन रनों से प्राप्त आउटपुट को चिपकाते हुए ffprobe -i input.mp4 -select_streams v -show_frames -of csv -show_entries frame=pict_type, फिर कोशिकाओं को रंग दिया। मुझे डर है कि कोई सार्वजनिक चर्चा नहीं हो रही है, लेकिन मैं देखूंगा कि क्या मैं फिर से पाए गए कुछ लिंक खोद सकता हूं।
23

क्या आप -force_key_frames expr:gte(t,n_forced*GOP_LEN_IN_SECONDS)फार्म के साथ अपने प्रयोग को फिर से आज़मा सकते हैं ? मैंने बस कोशिश की और पाया कि जब मैं स्ट्रीम में अतिरिक्त आई फ्रेम थे, तो यह डीआईडी ​​मेरे नियम का पालन करता है। एक पर्ल प्रोग्राम "उत्तर" के रूप में अनुसरण करेगा, क्योंकि आप टिप्पणियों में स्पष्ट रूप से मार्कअप का उपयोग नहीं कर सकते हैं।
मार्क गेरोलिमेटोस

दिलचस्प। मेरा मानना ​​है कि यह एक अलग "वास्तविक" उत्तर के लायक है यदि आपको पता चला कि यह काम करता है। (स्टैक एक्सचेंज साइटें इस चर्चा-शैली के उत्तर के लिए वास्तव में अच्छी नहीं हैं।) पिछली बार जब मैंने जाँच की -force_key_framesथी, तो मेरे लिए काम नहीं किया था, और इसलिए मैंने इसे फिर कभी कोशिश नहीं की। यह एक साल पहले की तुलना में अधिक था। शायद यह एक बग था। मैं जल्द ही फिर से कोशिश करूँगा।
slhck

12

यहाँ मेरे पचास सेंट केस के लिए है।

विधि 1:

libx264 के तर्कों के साथ खिलवाड़ करना

-c: v libx264 -x264opts keyint = GOPSIZE: min-keyint = GOPSIZE: दर्शनीय स्थान -1

वांछित अंतराल पर ही आइफ्रेम उत्पन्न करें।

उदाहरण 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

इस तरह की उम्मीद के अनुसार iframes उत्पन्न करें:

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

विधि 2 का मूल्यह्रास किया जाता है। लोप।

विधि 3:

हर N सेकंड (MAYBE) में एक कीफ़्रेम डालें:

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

उदाहरण 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

एक अलग तरीके से एक आइफ्रेम उत्पन्न करें:

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

जैसा कि आप देख सकते हैं कि यह हर 2 सेकंड में और अगरबत्ती (फ्लोटिंग पार्ट के साथ सेकंड) पर जगह देता है, जो मेरी राय में वीडियो स्ट्रीम जटिलता के लिए महत्वपूर्ण है।

Genearated फ़ाइल का आकार बहुत समान हैं। बहुत अजीब है कि यहां तक ​​कि विधि 3 में अधिक keyframes के साथ यह मानक x264 लाइब्रेरी एल्गोरिथ्म की तुलना में कभी-कभी कम फ़ाइल उत्पन्न करता है।

एचएलएस स्ट्रीम के लिए कई बिटरेट फाइल बनाने के लिए हम विधि तीन चुनते हैं। यह पूरी तरह से विखंडू के बीच 2 सेकंड के साथ संरेखित होता है, उनके पास हर चंक की शुरुआत में iframe होता है और उनके पास जटिल दृश्यों पर अतिरिक्त iframes होता है जो उन उपयोगकर्ताओं के लिए बेहतर अनुभव प्रदान करता है जिनके पास एक पुरानी डिवाइस है और वे x264 उच्च प्रोफ़ाइल प्लेबैक नहीं कर सकते हैं।

आशा है कि यह किसी की मदद करता है।


शानदार, अपने 50 सेंट के लिए धन्यवाद!
ब्रूनोफेन्गल

7

इसलिए उत्तर लगता है:

  • विधि 1 को काम करने के लिए सत्यापित किया गया है, लेकिन यह libx264बहुत ही उपयोगी है, और इसमें बहुत उपयोगी scenecutविकल्प को समाप्त करने की लागत पर आता है libx264
  • विधि 3 अप्रैल 2015 के FFMPEG संस्करण के रूप में काम करता है, लेकिन आपको इस पोस्ट के नीचे शामिल स्क्रिप्ट के साथ अपने परिणामों को सत्यापित करना चाहिए, क्योंकि FFMPEG प्रलेखन विकल्प के प्रभाव के अनुसार अस्पष्ट है। यदि यह काम करता है, तो यह दो विकल्पों में से श्रेष्ठ है।
  • विधि 2 का उपयोग न करें, -gयह पदावनत प्रतीत होता है। यह न तो काम करने के लिए प्रकट होता है, न ही यह स्पष्ट रूप से प्रलेखन में परिभाषित किया गया है, न ही सहायता में पाया जाता है, और न ही यह कोड में उपयोग किया जाता है। कोड निरीक्षण से पता चलता है कि -gविकल्प MPEG-2 धाराओं के लिए है (PAL और NTSC के संदर्भ में कोड स्टैनज भी हैं!)।

इसके अलावा:

  • विधि 3 के साथ उत्पन्न फाइलें विधि 1 से थोड़ी बड़ी हो सकती हैं, क्योंकि अंतरालीय I फ्रेम (कीफ्रेम) की अनुमति है।
  • आपको स्पष्ट रूप से "-r" ध्वज को दोनों मामलों में सेट करना चाहिए, भले ही विधि 3 अगले फ्रेमशॉट में I फ्रेम रखता है या बाद में निर्दिष्ट समय । "-R" झंडे को सेट करने में विफलता आपको स्रोत फ़ाइल की दया पर रखती है, संभवतः एक चर फ्रेम दर के साथ। असंगत डैश संक्रमण हो सकता है।
  • FFMPEG दस्तावेज में चेतावनी के बावजूद, विधि 3 है नहीं दूसरों की तुलना में कम कुशल। वास्तव में, परीक्षण बताते हैं कि यह विधि 1 की तुलना में थोड़ा अधिक कुशल हो सकता है।

के लिए स्क्रिप्ट -force_key_framesविकल्प के

यहाँ एक छोटा सा PERL कार्यक्रम है, जिसका उपयोग मैंने slhck के ffprobe सुझाव के आउटपुट के आधार पर I- फ्रेम ताल को सत्यापित करने के लिए किया था। यह सत्यापित करने के लिए लगता है कि -force_key_framesविधि भी काम करेगी, और इसके लिए अनुमति देने का अतिरिक्त लाभ हैscenecut फ़्रेम के । मुझे इस बात का बिलकुल भी अंदाजा नहीं है कि एफएफएमपीजी यह काम कैसे करता है, या अगर मैं किसी तरह से किस्मत से निकला हूं क्योंकि मेरी धाराएं अच्छी तरह से वातानुकूलित होती हैं।

मेरे मामले में, मैंने 6 सेकंड या 180 फ्रेम के अपेक्षित जीओपी आकार के साथ 30fps पर एनकोड किया। मैंने 180 का उपयोग किया, क्योंकि इस कार्यक्रम में गोपियों के तर्क ने 180 के प्रत्येक गुणक पर एक I फ्रेम को सत्यापित किया, लेकिन इसे 181 में सेट किया (या कोई अन्य संख्या जो कि 180 का गुणन नहीं है) ने इसकी शिकायत की।

#!/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;
}

बस एक नोट: चूंकि यह एक प्रश्नोत्तर साइट है और वास्तव में एक चर्चा मंच नहीं है जहां पदों को कालानुक्रमिक रूप से क्रमबद्ध किया जाता है , इसलिए सभी सूचनाओं को एक उत्तर में रखना सबसे अच्छा है , ताकि समाधान खोजने वाले लोगों को सिर्फ एक पोस्ट पढ़ना है और न देखना है किसने क्या पोस्ट किया, कब :) मैंने आपके उत्तर मर्ज किए और इस पर आपको +1 भी दिया। चूंकि क्रॉस पोस्टिंग की अनुमति नहीं है , मैं आपको वीडियो साइट पर अपना प्रश्न हटाने का सुझाव दूंगा। लोगों को यहां उत्तर मिल जाएगा।
slhck

1
मैं सिर्फ एक और सोचा था (वास्तव में यह FFmpeg मेलिंग सूची पर उठाया गया था)। जब आप उपयोग करते हैं force_key_frames, तो यह एक्स 264 बिट आवंटन एल्गोरिथ्म को गड़बड़ कर देता है, इसलिए यह आपको निश्चित कीफ़्रेम अंतराल सेट करने की तुलना में बदतर गुणवत्ता दे सकता है।
मई'15

बकवास। फिर भी FFMPEG के लिए एक और कारण यह करने के लिए एक codec-nonspecfic तरीका प्रदान करता है, एक तर्क जो "प्रश्न में कोडेक के लिए सबसे अच्छा काम करेगा"। मैंने इसके लिए
एफएफएमपीईजी के टीआरसी के

@ श्लोक: क्या आप कृपया अधिक जानकारी दे सकते हैं? मैंने मई 2015 में मेलिंग सूची अभिलेखागार में देखा है, लेकिन कुछ भी नहीं मिला। नीचे की रेखा "विधि 3" के बारे में भूल जाएगी और "विधि 1" से चिपकेगी।
schieferstapel

3
@MarkGerolimatos: के बारे में -g, आप कहते हैं, "यह न तो काम करता दिखाई देता है, ... और न ही यह कोड में उपयोग किया जाता है।" मैंने जाँच की और इनपुट का gसंग्रह इसमें संग्रहीत है avctx->gop_sizeऔर libx264 इसका उपयोग करता है x4->params.i_keyint_max = avctx->gop_size;:। जब मैं इस उत्पन्न परीक्षण फ़ाइल की जांच करता ffmpeg -i a-test-file.mp4 -g 37 -t 15 gtest.mp4हूं : तो , मुझे बिल्कुल कीफ़्रेम मिलता है 0,37,74,111,148,185,222,259,296,333,370। यदि दृश्य परिवर्तन शुरू हो जाता है, और इसके लिए -sc_thresholdसेट किया जा सकता है , तो एक GOP छोटा हो सकता है, जिसे x264 द्वारा भी चुना जाता है।
ज्ञान

4

मैं कुछ जानकारी यहाँ जोड़ना चाहता था क्योंकि मेरी गुगली ने इस चर्चा को काफी हद तक मेरी खोज में खींच लिया था ताकि मैं अपने डीएएसएच को अलग करने के तरीके को खोजने का प्रयास कर सकूँ जो मुझे चाहिए था, और मुझे जो जानकारी मिली थी, उसमें से कोई भी पूरी तरह से सही नहीं था।

छुटकारा पाने के लिए पहले कई गलत धारणाएँ:

  1. सभी आई-फ्रेम समान नहीं हैं। बड़े "मैं" फ्रेम और छोटे "मैं" फ्रेम हैं। या सही शब्दावली, आईडीआर आई-फ्रेम्स और गैर-आईडीआर आई-फ्रेम्स का उपयोग करने के लिए। आईडीआर आई-फ्रेम (कभी-कभी "कीफ्रेम" कहा जाता है) एक नया जीओपी बनाएगा। गैर-आईडीआर फ्रेम नहीं होगा। वे एक GOP के अंदर होना चाहते हैं जहां एक दृश्य परिवर्तन होता है।

  2. -x264opts keyint=GOPSIZE:min-keyint=GOPSIZEDo यह वह नहीं करता है जो आप सोचते हैं कि यह करता है। यह पता लगाने में मुझे थोड़ा समय लगा। यह पता चला min-keyintहै कि कोड में सीमित है। इससे अधिक होने की अनुमति नहीं है (keyint / 2) + 1। तो के लिए मूल्य में इन दो चर परिणाम के लिए एक ही मान निर्दिष्ट min-keyintआधे से नीचे गिरा दिया हो रही है जब एन्कोडिंग।

यहाँ बात यह है: दृश्य-कट वास्तव में बहुत अच्छा है, विशेष रूप से वीडियो में जिसमें तेजी से कठोर कटौती होती है। यह इसे अच्छा और कुरकुरा रखता है, इसलिए मैं इसे निष्क्रिय नहीं करना चाहता, लेकिन साथ ही मैं एक निश्चित GOP आकार प्राप्त नहीं कर सका जब तक कि यह सक्षम था। मैं दृश्य-कट सक्षम करना चाहता था, लेकिन केवल गैर-आईडीआर आई-फ्रेम का उपयोग करने के लिए। लेकिन यह काम नहीं कर रहा था। जब तक मैं ग़लतफ़हमी # 2 के बारे में (बहुत पढ़ने से) पता लगा।

यह पता चला है कि मुझे keyintअपना इच्छित GOP आकार दोगुना करने की आवश्यकता है । इसका मतलब है कि min-keyintमेरे इच्छित जीओपी आकार (इसे आधे में काटने वाले आंतरिक कोड के बिना) के लिए सेट किया जा सकता है, जो जीओपी आकार के अंदर आईडीआर आई-फ्रेम का उपयोग करने से दृश्य-कट का पता लगाने से रोकता है क्योंकि फ्रेम आखिरी आईडीआर आई-फ्रेम के बाद से गिनती है हमेशा से कम min-keyinit

और अंत में स्थापित करने के force_key_frameदुगुने आकार ओवरराइड विकल्प keyint। तो यहाँ क्या काम करता है:

मैं 2 सेकंड विखंडू में सेगमेंट पसंद करता हूं, इसलिए मेरा GOPSIZE = Framerate * 2

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

आप ffprobe का उपयोग करके सत्यापित कर सकते हैं:

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

उत्पन्न CSV फ़ाइल में प्रत्येक पंक्ति आपको बताएगी: 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

इसका नतीजा यह है कि आपको केवल निश्चित GOPSIZEअंतराल पर आईडीआर आई-फ्रेम्स को देखना चाहिए , जबकि अन्य सभी आई-फ्रेम नॉन-आईडीआर आई-फ्रेम्स हैं जिन्हें सीन-कट डिटेक्शन द्वारा आवश्यकतानुसार डाला गया है।


ये बहुत शानदार था! यह बहुत उल्टा था, प्रयास में लगाने के लिए धन्यवाद। और संक्षेप में, मैं "I- फ्रेम्स" और "i- फ्रेम्स" की आपकी परिभाषा को वैचारिक (जो कि, libx264 में अन्वेषण योग्य नहीं है) मानती है, और यह कि "अधिकतम * 2" क्या आप इसे लागू करना चाहते थे?
मार्क जेरोलिमेटोस

हां, यह वैचारिक था, हालांकि मैंने देखा है कि लोग आईडीआर और गैर-आईडीआर आई-फ्रेम के बीच अंतर करने के लिए "आई" बनाम "आई" का उपयोग करते हैं। और हाँ, वांछित गोपी आकार * 2 के लिए कीनिन सेट करना गैर-आईडीआर आई-फ्रेम होने के लिए गोप के अंदर सभी I फ्रेम को बाध्य करने का एक तरीका है। फिर x264opts में ffmpeg -force-key-over-rides key-init। मूल रूप से यह वांछित परिणाम प्राप्त करने के लिए एक बहुत ही पिछड़ा हुआ तरीका है जो कि संभव होगा यदि x264 कोड ने आपको मिन-कीनित और कीनीट को समान मूल्य पर सेट करने की अनुमति दी।
रूबेन

... जबकि दृश्य-कट का पता लगाने में दोनों सक्षम हैं और निश्चित GOP आकार प्राप्त करते हैं।
रूबेन

अपने भयानक काम के लिए फिर से धन्यवाद! लगता है कि हमें इसे प्रभावित करने के लिए एक कम "पिछड़े" तरीके की आवश्यकता है
मार्क गेरोलिमेटोस

क्या यहाँ rc-lookahead आवश्यक है? यह mbtree और VBV को प्रभावित करता है, लेकिन क्या यह आई-फ्रेम पीढ़ी को प्रभावित करता है?
अलेक्जेंडर Svetkin

0

ऐसा लगता है कि यह वाक्यविन्यास काम नहीं करता है। Ive ने हमारे VOD कंटेंट के साथ-साथ लाइव कंटेंट (फाइल डंप) पर भी काफी परीक्षण किया है और कभी-कभी एग्ज़ाइटिन iframe काम नहीं करता है और ट्रिगर करता है:

एक i50 के लिए सिंटैक्स-> p50 अपकेंद्रण, 2 सेकंड गोप / खंड, शुरुआत में IDR, iframes inbetween यदि आवश्यक हो

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

इस बारे में चिकोटी के पास एक पोस्ट है। वे बताते हैं कि उन्होंने कई कारणों से अपने स्वयं के कार्यक्रम का उपयोग करने का निर्णय लिया; उनमें से एक यह था कि ffmpeg आपको अलग-अलग थ्रेड्स में अलग-अलग x264 इंस्टेंस चलाने नहीं देता, बल्कि अगले आउटपुट पर जाने से पहले सभी निर्दिष्ट थ्रेड्स को एक आउटपुट में एक फ्रेम में दे देता है।

यदि आप वास्तविक समय की स्ट्रीमिंग नहीं कर रहे हैं, तो आपके पास अधिक लक्जरी हैं। 'सही' तरीका संभवत: -जी के साथ निर्दिष्ट जीओपी आकार के साथ एक रिज़ॉल्यूशन पर एनकोड करना है, और फिर उसी स्थान पर कीफ़ोर्स को मजबूर करने वाले अन्य रिज़ॉल्यूशन को एनकोड करना है।

यदि आप ऐसा करना चाहते हैं, तो आप keyf टाइम्स को प्राप्त करने के लिए ffprobe का उपयोग कर सकते हैं और फिर एक ffmpeg कमांड में परिवर्तित करने के लिए एक शेल स्क्रिप्ट या वास्तविक प्रोग्रामिंग भाषा का उपयोग कर सकते हैं।

लेकिन अधिकांश सामग्री के लिए, हर 5 सेकंड में एक कीफ्रेम और हर 5 सेकंड में दो कीफ्रेम होने के बीच बहुत कम अंतर होता है (एक मजबूर और एक दर्शनीय स्थल से)। यह पी-फ्रेम और बी-फ्रेम के आकार के औसत आई-फ्रेम आकार के बारे में है। यदि आप सामान्य सेटिंग्स के साथ x264 का उपयोग करते हैं (केवल यही कारण है कि मुझे लगता है कि आपको प्रभावित करने के लिए कुछ भी करना चाहिए यदि आप सेट -मिन करते हैं, तो x264 को आसान सामग्री पर बिटरेट का उपयोग करने से रोकने के खराब तरीके के रूप में; यह सभी फ्रेम प्रकारों को एक ही मूल्य तक सीमित करता है; , मुझे लगता है) और 46 kB के I- फ्रेम औसत आकार, पी-फ्रेम 24 kB, B- फ्रेम 17 kB (पी-फ्रेम के रूप में लगातार आधे) जैसे परिणाम प्राप्त करें, फिर 30 सेकंड में हर सेकंड एक अतिरिक्त I- फ्रेम करें फ़ाइल आकार में केवल 3% की वृद्धि है। H264 और h263 के बीच का अंतर 3% की कमी से बना हो सकता है, लेकिन एक भी बहुत महत्वपूर्ण नहीं है।

अन्य प्रकार की सामग्री पर, फ़्रेम का आकार अलग होगा। निष्पक्ष होने के लिए, यह अस्थायी जटिलता और स्थानिक जटिलता के बारे में है, इसलिए यह केवल आसान सामग्री बनाम कठिन सामग्री नहीं है। लेकिन आम तौर पर, स्ट्रीमिंग वीडियो साइटों में एक बिटरेट सीमा होती है, और अपेक्षाकृत बड़े आई-फ़्रेम के साथ सामग्री आसान सामग्री होती है जिसे उच्च गुणवत्ता पर एन्कोड किया जाएगा चाहे कितना भी अतिरिक्त कीफ़्रेम जोड़ा जाए। यह बेकार है, लेकिन इस कचरे पर आमतौर पर ध्यान नहीं दिया जाएगा। सबसे बेकार मामला शायद एक वीडियो है जो एक गाने के साथ बस एक स्थिर छवि है, जहां प्रत्येक कीफ़्रेम बिल्कुल समान है।

एक बात मुझे यकीन नहीं है कि कैसे मजबूर keyframes दर सीमक के साथ बातचीत -maxrate और -bufsize के साथ सेट है। मुझे लगता है कि यहां तक ​​कि YouTube को भी हाल ही में लगातार गुणवत्ता देने के लिए बफर सेटिंग्स को सही ढंग से कॉन्फ़िगर करने में समस्याएं हुई हैं। यदि आप औसत बिटरेट सेटिंग्स का उपयोग कर रहे हैं, जैसा कि कुछ साइटों द्वारा देखा जा सकता है (क्योंकि आप हेडर / मूव एटम में x264 के विकल्पों का निरीक्षण कर सकते हैं। हेक्स संपादक के साथ) तो बफर मॉडल कोई समस्या नहीं है, लेकिन यदि आप उपयोगकर्ता-जनित सामग्री की सेवा, औसत बिटरेट उपयोगकर्ताओं को अपने वीडियो के अंत में एक काली स्क्रीन जोड़ने के लिए प्रोत्साहित करता है।

Ffmpeg का -g विकल्प, या आपके द्वारा उपयोग किया जाने वाला कोई अन्य एनकोडर विकल्प, एन्कोडर-विशिष्ट विकल्प पर मैप किया जाता है। तो '-x264-params keyint = GOPSIZE' '-g GOPSIZE' के बराबर है।

दृश्य पहचान का उपयोग करने के साथ एक समस्या यह है कि यदि आप जो भी कारण के लिए विशिष्ट संख्या के पास keyframes पसंद करते हैं। यदि आप प्रत्येक 5 सेकंड में keyframes निर्दिष्ट करते हैं और दृश्य पहचान का उपयोग करते हैं, और 4.5 पर एक दृश्य परिवर्तन होता है, तो इसका पता लगाया जाना चाहिए, लेकिन फिर अगला कीफ़्रेम 9.5 पर होगा। अगर समय इसी तरह बढ़ता रहा, तो आप 40, 45, 50, 55 के बजाय 42.5, 47.5, 52.5 आदि पर कीफ्रेम के साथ समाप्त हो सकते हैं। इसके विपरीत, यदि 5.5 पर कोई दृश्य परिवर्तन होता है, तो वहाँ होगा ५ और ५.५ पर एक कीफ्रेम एक दूसरे के लिए बहुत जल्दी होगा। Ffmpeg आपको यह निर्दिष्ट नहीं करने देता है कि "अगर अगले 30 फ्रेम के भीतर कोई दृश्य परिवर्तन नहीं हुआ है तो यहां एक कीफ़्रेम बनाएं।" कोई है जो C को समझता है, हालांकि वह विकल्प जोड़ सकता है।

चर-फ्रेम-दर वीडियो के लिए, जब आप ट्विच की तरह लाइव-स्ट्रीमिंग नहीं करते हैं, तो आपको स्थायी फ्रेम को स्थायी फ्रेम-दर में परिवर्तित किए बिना दृश्य परिवर्तनों का उपयोग करने में सक्षम होना चाहिए। यदि आप ffmpeg में 'सेलेक्ट' फ़िल्टर का उपयोग करते हैं और एक्सप्रेशन में 'सीन' कंटीन्यू का उपयोग करते हैं, तो डिबग आउटपुट (-v डीबग या एन्कोडिंग करते समय कई बार '+' दबाएं) सीन चेंज नंबर दिखाता है। यह शायद इससे अलग है, और उतना उपयोगी नहीं है, जितना कि x264 द्वारा उपयोग किया गया, लेकिन यह अभी भी उपयोगी हो सकता है।

प्रक्रिया, तब, शायद एक वीडियो परीक्षण करना होगा जो केवल की-फ़्रेम परिवर्तनों के लिए है, लेकिन शायद 2-पास का उपयोग करते हुए दर नियंत्रण डेटा के लिए उपयोग किया जा सकता है। (यह सुनिश्चित नहीं है कि उत्पन्न डेटा विभिन्न रिज़ॉल्यूशन और सेटिंग्स के लिए सभी उपयोगी है; मैक्रोब्लॉक-ट्री डेटा नहीं होगा।) इसे निरंतर-फ़्रैमरेट वीडियो में कनवर्ट करें, लेकिन जब आप तय करते हैं तो फ्रैमरेट को रोकते समय आउटपुट के बारे में इस बग को देखें। अन्य उद्देश्यों के लिए एफपीएस फ़िल्टर का उपयोग करें। अपने इच्छित कीफ़्रेम और GOP सेटिंग्स के साथ x264 के माध्यम से इसे चलाएं।

तो बस मूल चर फ्रेम दर वीडियो के साथ इन कीफ़्रेम समय का उपयोग करें।

यदि आप फ़्रेम के बीच 20-सेकंड के अंतराल के साथ पूरी तरह से पागल उपयोगकर्ता-उत्पन्न सामग्री की अनुमति देते हैं, तो चर फ्रेम-दर एन्कोड के लिए, आप आउटपुट को विभाजित कर सकते हैं, एफपीएस फ़िल्टर का उपयोग कर सकते हैं, किसी भी तरह चुनिंदा फ़िल्टर का उपयोग करें (शायद वास्तव में लंबी अभिव्यक्ति का निर्माण करें हर कीफ़्रेम समय) ... या हो सकता है कि आप परीक्षण वीडियो को इनपुट के रूप में उपयोग कर सकते हैं और या तो केवल कीफ़्रेम को डिकोड कर सकते हैं, यदि वह ffmpeg विकल्प काम करता है, या कीफ़्रेम का चयन करने के लिए चयन फ़िल्टर का उपयोग करें। फिर इसे सही आकार में स्केल करें (इसके लिए एक स्केल 2 एसआर फिल्टर भी है) और इस पर मूल वीडियो ओवरले करें। फिर इन वीडियो को मूल वीडियो के साथ मजबूर करने के लिए संयोजित करने के लिए इंटरलेव फ़िल्टर का उपयोग करें। यदि यह दो तख्ते में परिणत होता है, जो 0.001 सेकेंड के अलावा होता है, जो कि इंटरलेव फिल्टर को रोकता नहीं है, तो इस समस्या को दूसरे चुनिंदा फिल्टर के साथ स्वयं संबोधित करें। इंटरलेव फिल्टर के लिए फ्रेम बफर सीमा से निपटना यहां की मुख्य समस्या हो सकती है। ये सभी काम कर सकते हैं: सघन धारा (पंद्रो फिल्टर?) को बफर करने के लिए किसी प्रकार के फिल्टर का उपयोग करें; इनपुट फ़ाइल को कई बार देखें ताकि यह एक से अधिक बार डिकोड हो जाए और फ़्रेम को संग्रहीत न करना पड़े; 'स्ट्रीमसेलेक्ट' फिल्टर का उपयोग करें, जो मैंने कभी नहीं किया है, बिल्कुल केफ्रेम के समय पर; अपने डिफ़ॉल्ट व्यवहार को बदलकर या एक फ्रेम छोड़ने के बजाय बफर में सबसे पुराने फ्रेम को आउटपुट करने के लिए एक विकल्प जोड़कर इंटरलेव फ़िल्टर को बेहतर बनाएं। जो मैंने कभी नहीं किया है, बिल्कुल केफ्रेम के समय पर; अपने डिफ़ॉल्ट व्यवहार को बदलकर या एक फ्रेम छोड़ने के बजाय बफर में सबसे पुराने फ्रेम को आउटपुट करने के लिए एक विकल्प जोड़कर इंटरलेव फ़िल्टर को बेहतर बनाएं। जो मैंने कभी नहीं किया है, बिल्कुल केफ्रेम के समय पर; अपने डिफ़ॉल्ट व्यवहार को बदलकर या एक फ्रेम छोड़ने के बजाय बफर में सबसे पुराने फ्रेम को आउटपुट करने के लिए एक विकल्प जोड़कर इंटरलेव फ़िल्टर को बेहतर बनाएं।

हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.