video طريقة - كيفية استخراج مقاطع فيديو دقيقة مع ffmpeg؟




من مقطع (5)

ليست هناك حاجة لإضافة إطارات مفتاحية ؛ كما يقول بيتر ، إنها ببساطة مسألة الحصول على الخيارات في الترتيب الصحيح. ومع ذلك ، انظر https://trac.ffmpeg.org/wiki/Seeking للاطلاع على الدليل الرسمي النهائي حول كيفية القيام بذلك بشكل صحيح.

هذا ليس مجال سؤال جديد بشكل خاص هنا ، لكني جربت ما تم اقتراحه هناك دون الكثير من الحظ. لذا ، قصتي:

لقد حصلت على 15 ثانية من الفيديو المباشر من فيديو camera.mov الذي أريد استخلاص مقطع محدد ، والذي يمكنني التعرف عليه من خلال وقت البدء ووقت التوقف ، في ثوانٍ. لقد بدأت بمحاولة تنفيذ ما أسميه "استخراج نسخة": للحصول على الثواني من 9 إلى 12 ،

ffmpeg -i test.mov -vcodec copy -acodec copy -ss 9 -to 12 test-copy.mov

كانت هذه بداية سيئة ، ولكن هناك بعض الإطارات السوداء في بداية ونهاية المقطع ، والتي لا يمكنني الحصول عليها - يجب أن يكون تحريرًا نظيفًا من النص الأصلي. لذلك ، حاولت إعادة ترميز النسخة الأصلية إلى مقطع جديد تم قطعه:

ffmpeg -i test.mov -ss 00:00:09 -t 00:00:03 test-out.mov

هذا أفضل ، ولكن ليس تمامًا: لم تعد هناك إطارات سوداء في بداية المقطع ، ولكنها لا تزال موجودة في النهاية.

بعد بعض المزيد من التصفح والقراءة ، ثم أشك في أن المشكلة هي أن ffmpeg تواجه مشكلة في العثور على النقاط المناسبة بسبب عدم وجود إطارات مفتاحية في الفيديو الأصلي. لذا قمت بإعادة تشفير الفيديو الأصلي إلى (من المفترض) إضافة إطارات مفتاحية ، بطريقتين مختلفتين. نظرًا لأنني أريد أن أتمكن من اختيار الفيديو عند حدود ثانية ("من 9 ثوانٍ إلى 12 ثانية") ، فقد حاولت نسخ العديد من الاقتراحات عبر الويب ،

ffmpeg -i test.mov -force_key_frames "expr:gte(t, n_forced)" test-forced.mp4

و

ffmpeg -i test.mov -g 1 test-g-inserted.mp4

(لقد قمت ببناء هذه البرامج على أساس mp4 استنادًا إلى بعض التعليقات حول حاوية mp4 المطلوبة لدعم البحث في الإطار الرئيسي ، ولكنني بصراحة أخترق هنا.) ثم جربت عملية الاستخراج كما كان من قبل ، ولكن على مقاطع الفيديو الجديدة التي من المفترض أن تحتوي الآن على إطارات مفتاحية (keyframes) فيهم. لا حظ - فكلاهما يبدو متشابهين. البداية على ما يرام ولكن لا تزال هناك إطارات سوداء في النهاية. (FWIW ، كلا test-forced.mp4 و test-g-inserted.mp4 لهما أيضاً إطارات سوداء متتابعة).

إذن: ما زلت عالقاً ، وأرغب في ألا أكون كذلك. هل هناك أي إحصاءات حول ما أفعله خطأ؟ أشعر وكأنني قريب ، لكني في الحقيقة أحتاج للتخلص من تلك الإطارات السوداء ...


حسناً ، أولاً ، بافتراض أنك تعرفين البداية والتوقف. سنضيف إطارات رئيسية في تلك المدة.

ffmpeg -i a.mp4 -force_key_frames 00:00:09,00:00:12 out.mp4

في معظم الأوقات ، يمكنك قص الفيديو بشكل مثالي ولكن في حالتك لا يساعدك ؛ لذلك نحن تعتني بها الأمر أعلاه. هنا توخي الحذر لعدم إضافة الكثير من الإطارات الرئيسية حيث يمكن أن يكون هناك مشكلة أثناء الترميز وفقًا لـ Ffmpeg Docs .

الآن يمكنك مرة أخرى محاولة قطع الفيديو من وقت محدد.

ffmpeg -ss 00:00:09 -i out.mp4 -t 00:00:03 -vcodec copy -acodec copy -y final.mp4

سيؤدي ذلك إلى حل المشكلة نظرًا لأننا أضفنا الإطارات الرئيسية يدويًا عند نقاط البداية والنهاية للقص. عملت معي.

في صحتك.:)


أود أن أعرف أيضا. حتى الآن ، قمت بتحويل مقاطع الفيديو الخاصة بي بلا خسارة ، واستخرجت مقطعًا وأعدت تشفيرها بعد التعديل:

ffmpeg -i input -ss 9.48 -t 3.52 -c:v libx264 -crf 0 -g 1 -c:a copy TempIframe.mp4

ولكن هذه العملية تستغرق وقتا طويلا وفقدان ...

لقد جربت ما يلي دون نجاح:

ffmpeg -i source.mp4 -ss 1 -c:v copy -seek2any 1 -avoid_negative_ts 1 -safe 1 -c:a copy segment.mp4

أعتقد أن المشكلة التي يطرحها السؤال والإجابات الأخرى هي أنهم يستخدمون -ss كخيار في ملف الإخراج ، وليس في ملف الإدخال. معظم خيارات ffmpeg ليست عالمية ، ولكن بدلاً من ذلك تنطبق فقط على الملف الذي تسبقه. غالبًا ما لا يكون واضحًا في أي مكان يحتاج إليه الخيار ، لذلك يلزم إجراء التجربة والخطأ أحيانًا.

تستخدم بشكل صحيح ، قبل ملف الإدخال الذي يقصد تطبيقها على -ss و -t عملت بشكل جيد بالنسبة لي. عند تضمين الصوت في الإخراج ، اضطررت إلى استخدام -shortest كخيار لملف الإخراج ، أو الحصول على 2 دقيقة من الصوت مع 2 ثانية من الفيديو.

إصدار ffmpeg N-67413-g2a88c74 (مصدر git أساسًا من 14 ديسمبر 2014)

وهنا سطر الأوامر اعتدت على صنع مقطع في الآونة الأخيرة. (في الواقع تم تعديله ليكون مثالاً أفضل ، منذ أن تركت الصوت في هذا ، ولم أقم بذلك.)

ffmpeg -ss 120.2 -t 0.75 -i ../mcdeint.60p.lossless264.slow.mkv -c:a libopus -shortest -aspect 16:9 -preset veryslow -x264-params nr=250:ref=6 -crf 22 -movflags +faststart clip2.mkv

مع -c:a copy (مصدر يحتوي على صوت AC3) ، يبدأ التشغيل مع مشغل mplayer. ربما يمسك الصوت من بداية الإطار الصوتي الذي يحتوي على البداية ، ومن ثم يجب عليه استخدام aa / v offset في الحاوية. عند بدء التشغيل ، يستغرق الأمر جزءًا من الثانية حتى يتسنى للمقطع الصوتي الحصول على الفيديو قبل هذا الإزاحة ، وحتى ذلك الحين يتم تشغيل الفيديو بمعدل FPS منخفض جدًا. لذلك أنا xcoded الصوت. لا يمكن تشغيل opus ولا pcm_s16le في mp4 ، لذلك استخدمت حاوية mkv لهذا المثال.

المصدر عبارة عن ترميز x264 بدون فقدان ( -qp 0 ) من إخراج -qp 0 بطيء جدًا = 3: 1 ، mcdeint = 3: 1: 10 (في بعض الفيديو المتداخل BFF من قرص DVD NTSC ، من كاميرا DV). إنه ليس كل إطارات I ، إنه إطارات P مع فاصل زمني أساسي في keyframe.

ضبط -s بمقدار 0.2 ثانية فعل بالضبط ما كنت آمل ، لذلك يجب ffmpeg معالجة فك ترميز إلى النقطة المطلوبة. لم تكن مجرد مصادفة لإطار حيث أردت واحدة. ربما -accurate_seek هو الافتراضي؟ أنا أيضا الحصول على نفس النتيجة (بايت GIF بايت متطابقة بايت) كما عند استخدام مصدر فقدان ffvhuff كإدخال. (لكنه يعمل بشكل أسرع ، لأنه لا يحتاج إلى فك ترميزه إلى النقطة المطلوبة.)

هناك خيار آخر يمكن أن يكون مناسبًا هو -seek2any ، ولكنه يقول "السعي إلى عدم الإطار الرئيسي على مستوى demuxer" ، والذي يبدو أنه سيسمح لك بالبحث بطرق من شأنها أن تنتج مخرجات مشوهة. (على سبيل المثال ، بدء فك التشفير دون الحاجة إلى توليد المراجع التي يتطلبها الإطار الحالي ، فما عليك سوى استخدام الرمادي بالكامل؟)

لم أحاول استخدام -c:v copy ، لأنني أقطع مقطعًا قصيرًا حقًا ، لذلك أعلم أنه لن يكون هناك إطارات لأني أحتاج إليها.

هذا هو سطر الأوامر الذي استخدمته بالفعل ، لعمل مقطع قصير من slo-mo بدون صوت.

ffmpeg -ss 120.2 -t 0.75 -i ../vid.yadif3.1,mcdeint3.1.10.ffvhuff.mkv -an -shortest -aspect 16:9 -c:v libx264 -preset veryslow -x264-params nr=250:ref=6 -crf 22 -filter:v "setpts=3.0*PTS" -movflags +faststart -r 20 clip.mp4

لاحظ أن -r 20 مهم ، لأنه بخلاف mkv ، يكون إخراج MP4 لـ ffmpeg ثابتًا بمعدل الإطار فقط (تحرير: لأن -vsync vfr ليس الافتراضي مع muxer mp4). بدون إخبارها بشكل مختلف ، فإنها ستقوم بإعداد FPS = FPS للإدخال ، وإطارات مكررة عند الحاجة لتحقيق ذلك. يمكن لـ x264 و gif المتحركة (مع الشفافية) تشفير الإطارات المكررة بكفاءة عالية ، ولكنها لا تزال سخيفة.

قبل طهي هذا كمثال ، كنت قد فعلت ذلك في 2 خطوات ، واحد خرج إلى MKV ، ثم ffmpeg -i clip.mkv -c:v copy -movflags +faststart -r 20 clip.mp4 to remux. راجع للشغل ، فإنه من الممكن تغيير إطار في الثانية من الفيديو عند remuxing ، دون xcoding ، فقط ليس مع ffmpeg. https://superuser.com/questions/740196/reducing-video-size-with-avconv-why-does-the-size-increase . ولكن على أي حال ، أرسلت ffmpeg 45 إطارًا فقط إلى libx264 عند إنشاء mkv ، على الرغم من أنها تعتقد أنها كانت تصنع فيديو 2.2 مرة بمعدل 60 إطارًا في الثانية. لا تستخدم ffmpeg مع mp4 للعمل مع عناصر FPS المتغيرة.

تحرير: تبين الافتراضات ffmpeg إلى -vsync vfr mkv ، ولكن ليس لـ mp4. مع -vsync vfr ، يمكن أن يكتب ffmpeg VFR إلى خرج mp4 على ما يرام.

ومرة أخرى لإخراج gif ، إذا قررت عدم طرحه مع فيديو HTML5 ( <video controls autoplay loop> <source src="clip.mp4" type="video/mp4"> </video> )

ffmpeg -ss 120.2 -t 0.75 -i ../vid.yadif3.1,mcdeint3.1.10.ffvhuff.mkv -an -shortest -aspect 16:9 -filter:v "setpts=3.0*PTS,scale=854x480" -r 20 clip.gif

اضطررت إلى استخدام scale= نظرًا لأن حاوية gif لا تخزن نسبة عرض إلى ارتفاع ، لذا لا يمكن ضبطها تلقائيًا عند التشغيل. (يتم تحجيم الفيديو 720 × 480 بكسل 16: 9 إلى 854 × 480 عند التشغيل. في الواقع يجب أن يكون 853.333 ، ولكن ذلك يتم تقريبه ، ثم تخزن ffmpeg 853 × 480 في حاوية mkv ، ومن ثم استخدام 16: 9 في كل وقت ، لذا سيعمل mp4 تخزين نسبة العرض إلى الارتفاع المناسبة [SAR 32:27 DAR 16:9] ، بدلاً من [SAR 186:157 DAR 279:157] )


الإجابة على السؤال المطروح ...
لا ، لا يكفي أن يكون لديك هذه السمات ، حتى تتمكن من تشغيل الوسائط مع الصوت تلقائيًا ، يلزمك تسجيل إيماءة مستخدم في وثيقتك.

ولكن هذا القيد ضعيف جدًا: إذا تلقيت إيماءة المستخدم هذه في المستند الأصل ، وتم تحميل الفيديو الخاص بك من إطار iframe ، فيمكنك تشغيله ...

لذلك خذ على سبيل المثال هذا الكمان ، وهو فقط

<video src="myvidwithsound.webm" autoplay=""></video>

عند التحميل لأول مرة ، وإذا لم تنقر فوق أي مكان ، فلن يعمل ، لأنه ليس لدينا أي حدث مسجل حتى الآن.
ولكن بمجرد النقر فوق الزر "تشغيل" ، فإن المستند الأصل (jsfiddle.net) تلقى إيماءة للمستخدم ، والآن يتم تشغيل الفيديو ، على الرغم من أنه يتم تحميله تقنيًا في مستند مختلف.

ولكن المقتطف التالي ، لأنه يتطلب منك النقر فعليًا على زر " تشغيل شفرة المقتطف" ، سيتم تشغيله تلقائيًا.

<video src="https://upload.wikimedia.org/wikipedia/commons/transcoded/2/22/Volcano_Lava_Sample.webm/Volcano_Lava_Sample.webm.360p.webm" autoplay=""></video>

هذا يعني أن إعلانك ربما كان قادرًا على اللعب لأنك قدمت إيماءة للمستخدم إلى الصفحة الرئيسية.

الآن ، لاحظ أن Safari و Mobile Chrome لديهما قواعد أكثر صرامة من ذلك ، وسيطلبان منك تشغيل ما لا يقل عن مرة واحدة بطريقة play() بطريقة برمجية على عنصر <video> أو <audio> من معالج حدث المستخدم نفسه.

btn.onclick = e => {
  // mark our MediaElement as user-approved
  vid.play().then(()=>vid.pause());
  // now we can do whatever we want at any time with this MediaElement
  setTimeout(()=> vid.play(), 3000);
};
<button id="btn">play in 3s</button>
<video
  src="https://upload.wikimedia.org/wikipedia/commons/transcoded/2/22/Volcano_Lava_Sample.webm/Volcano_Lava_Sample.webm.360p.webm" id="vid"></video>

وإذا لم تكن بحاجة إلى الصوت ، فببساطة لا تقوم بإرفاقه بالوسائط الخاصة بك ، يُسمح أيضًا بتشغيل مقطع فيديو به مسار فيديو فقط ، وسيؤدي ذلك إلى تقليل استخدام النطاق الترددي للمستخدم.





video ffmpeg video-editing