سؤال الصور المصغرة ذات مغزى لملف فيديو باستخدام FFmpeg


يمكن لـ FFmpeg التقاط الصور من مقاطع الفيديو التي يمكن استخدامها كصور مصغرة لتمثيل الفيديو. يتم التقاط الطرق الأكثر شيوعا للقيام بذلك في FFmpeg Wiki.

ولكن ، لا أريد اختيار إطارات عشوائية في بعض الفترات. لقد وجدت بعض الخيارات باستخدام الفلاتر على FFmpeg لالتقاط تغييرات المشهد:

مرشح thumbnail يحاول العثور على الأطر الأكثر تمثيلاً في الفيديو:

ffmpeg -i input.mp4 -vf  "thumbnail,scale=640:360" -frames:v 1 thumb.png

ويختار الأمر التالي الإطارات التي تحتوي على أكثر من 40٪ من التغييرات مقارنةً بالتغييرات السابقة (ومن المحتمل أن تكون تغييرات المشهد) وتنتج سلسلة من 5 PNG.

ffmpeg -i input.mp4 -vf  "select=gt(scene\,0.4),scale=640:360" -frames:v 5 thumb%03d.png

رصيد المعلومات للأوامر المذكورة أعلاه ل فابيو سوناتي. بدا الثاني أفضل حيث يمكنني الحصول على صور واختيار الأفضل. لقد حاولت ذلك وولدت نفس الصورة 5 مرات.

قادني المزيد من التحقيقات إلى:

ffmpeg -i input.mp4 -vf "select=gt(scene\,0.5)" -frames:v 5 -vsync vfr  out%02d.png

-vsync vfr يضمن أن تحصل على صور مختلفة. لا يزال هذا دائمًا يختار الإطار الأول من الفيديو ، وفي معظم الحالات يكون الإطار الأول عبارة عن أرصدة / شعار وليست ذات معنى ، لذلك أضفت -ss 3 لتجاهل أول 3 ثوانٍ من الفيديو.

يبدو الأمر النهائي كما يلي:

ffmpeg -ss 3 -i input.mp4 -vf "select=gt(scene\,0.5)" -frames:v 5 -vsync vfr out%02d.jpg

كان هذا أفضل ما يمكنني القيام به. لقد لاحظت أنه منذ أن اخترت 5 مقاطع فيديو فقط ، فغالبًا ما يكون معظمها من بداية الفيديو وقد يفوتك مشاهد مهمة تحدث لاحقًا في الفيديو

أود أن أختار عقلك لأية خيارات أخرى أفضل.


71
2018-01-18 08:35


الأصل


أمثلة أمر جيد. FWIW ، لم أواجه أي مشاكل مع صور JPEG التي أنشأتها FFmpeg على OS X (10.8 ، FFmpeg 1.1 وأدناه). الأمر الثاني إلى الأخير يعمل بشكل جيد بالنسبة لي - وكذلك الأمر الأخير - ولا شيء من هذه النتائج في ملفات JPG الفارغة. أنا مع ترجمة libopenjpeg.. لست متأكدا إذا كان هذا يحدث فرقا. - slhck
شكرا slhck. عدلت السؤال مع تفاصيل ffmpeg config / version. لم أقم بالترقية إلى 1.1 على هذا الجهاز. سأفعل ذلك ونرى ما إذا كان سيغير أي نتائج. - d33pika
إذن أنت على أوبونتو؟ يمكنك محاولة أحدث نسخة جيت ماستر من بناء ثابت أو تجميع نفسك وتشغيل مرة أخرى؟ أو أحدث مستقر. أنا فقط دققت ، فإنه يستخدم mjpeg التشفير بالنسبة لي كذلك ، ودققت أيضا jpegoptim و exiv2، كلاهما يعمل بشكل جيد بالنسبة لي مع جميع النتائج JPG من الأوامر سبيل المثال الخاص بك. - slhck
لقد قمت بتحديث ، ويعمل الآن! أعتقد أن الإصدار السابق كان به بعض الخلل. - d33pika
هل يمكنك المضي قدمًا وإصدار النسخة الجديدة من الحل ، ويفضل أن يكون ذلك مع رابط إلى التغيير يوضح الخطأ الذي واجهته وثبت بعد ذلك بإصدار جديد؟ - Lizz


الأجوبة:


ماذا عن البحث ، بشكل مثالي ، أول إطار تغيير 40٪ داخل كل فترة زمنية تمتد 5 مرات ، حيث تمتد الفترات الزمنية الأولى والثانية والثالثة والرابعة والخامسة 20٪ من الفيديو.

يمكنك أيضًا تقسيمها إلى 6 فترات زمنية وتجاهل الإصدار الأول لتجنب الاعتمادات.

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

...شيء مثل:

ffmpeg -ss 3 -i input.mp4 -vf "select=gt(scene\,0.4)" -frames:v 5 -vsync vfr -vf fps=fps=1/600 out%02d.jpg

23
2018-06-15 21:35



نعم ، يساعد ذلك في التقاط الصور المصغرة من أقسام مختلفة من الفيديو. شكر! - d33pika
الحصول على صور سوداء أو بيضاء بالكامل. كيف يمكنني تجنب تلك؟ - d33pika
أما بالنسبة للإطارات البيضاء ، فقد أصبح الأمر معقدًا ، ولكن يبدو أن هناك طريقة: 1. إزالة الإطارات السوداء 2. نفي (يتحول الأبيض إلى أسود) 3. أخرج الإطارات البيضاء 4. نفي مرة أخرى 5. استخرج الصور المصغرة (إذا تمكنت من إزالة الإطارات السوداء أو البيضاء ، وخاصة على سطر واحد ، فهل يمكنك نشرها مرة أخرى هنا؟ يمكنني إضافتها إلى الإجابة لقراء المستقبل ... أو في الواقع يمكنك إنشاء سؤال وجواب جديد كنت بالتأكيد سأشاهده.) - A.M.
لتجنب الصور المملة مثل الأسود والأبيض العادي: قم بإنشاء صور مصغّرة أكثر مما تحتاج ، قم بضغطها باستخدام jpeg ، واختر الصور ذات حجم الملف الأكبر. هذا يعمل بشكل جيد بشكل مدهش في حد ذاته للحصول على صور مصغرة لائقة. - Sam Watkins
لم يعمل هذا الأمر ، حصلت على الخطأ Unable to find a suitable output format for 'fps=fps=1/600'. الحل هو إضافة -vf قبل تلك الحجة (انظر stackoverflow.com/questions/28519403/ffmpeg-command-issue) - John Wiseman


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

الزائفة رمز

for X in 1..N
  T = integer( (X - 0.5) * D / N )  
  run `ffmpeg -ss <T> -i <movie>
              -vf select="eq(pict_type\,I)" -vframes 1 image<X>.jpg`

أين:

  • د - مدة الفيديو تقرأ من ffmpeg -i <movie> وحده أو ffprobe الذي لديه الكاتب إخراج JSON لطيفة راجع للشغل
  • N - إجمالي عدد الصور المصغرة التي تريدها
  • X - الرقم المصغر ، من 1 إلى N
  • تي - نقطة الوقت لالتقاط الصور المصغرة

ببساطة ما ورد أعلاه يكتب أسفل إطار المفتاح المركزي لكل قسم من الفيلم. مثلا إذا كان الفيلم يبلغ طوله 300 ثانية وكنت تريد 3 صور مصغرة ، فستحتاج إلى إطار رئيسي واحد بعد الخمسينات و 150 و 250 ثانية. بالنسبة إلى 5 صور مصغرة ، ستكون 30 صورة مصغرة ، و 90 ، و 150 ، و 210 ، و 270. يمكنك ضبط N بناءً على مدة الفيلم D ، على سبيل المثال ، سيحتوي الفيلم المكون من 5 دقائق على 3 صور مصغرة ، ولكن سيكون هناك أكثر من ساعة واحدة في 20 صورة مصغرة.

أداء

كل استدعاء من أعلاه ffmpeg يأخذ الأمر جزءًا من الثانية (!) لـ ~ 1GB H.264. هذا لأنه يقفز على الفور <time> موقف (العقل -ss قبل -i) ويأخذ إطار المفتاح الأول الذي يكمل JPEG عمليا. لا يوجد وقت ضائع لعرض الفيلم لمطابقة موضع التوقيت الدقيق.

المعالجة البعدية

يمكنك خلط أعلاه مع scale أو أي طريقة أخرى لتغيير الحجم. يمكنك أيضًا إزالة الإطارات ذات الألوان الصلبة أو محاولة مزجها مع فلاتر أخرى مثل thumbnail.


5
2017-10-06 20:21



واو تتحرك -ss N الى قبل -i هو نصيحة مذهلة. شكرا جزيلا! - apinstein


فعلت ذات مرة شيئًا مشابهًا ، ولكنني صدّرت كل إطارات الفيديو (بمعدل 1 إطار في الثانية) وقارنتها باستخدام أداة perl وجدتها والتي تحسب الفرق بين الصور. قارنت كل إطار بالصور المصغرة السابقة ، وإذا كانت مختلفة عن جميع الصور المصغرة ، فقد أضفتها إلى مجموعة الصور المصغرة. وتتمثل الميزة هنا في أنه إذا انتقل الفيديو التابع لك من المشهد أ إلى ب وإعادته إلى "أ" ، فستصدر ffmpeg إطارين من "أ".


2
2018-03-17 14:36



ما العوامل التي استخدمتها لمقارنة صورتين؟ - d33pika
لسوء الحظ ، لا أتذكر ، لقد كان منذ فترة طويلة. تحتاج إلى أن تقرر أولاً الطريقة المقارنة التي يمكن استخدامها ، ثم قم ببعض الاختبارات لإيجاد عامل صحيح. هذا لا ينبغي أن يستغرق وقتا طويلا. - Eran Ben-Natan
أنا فقط أفكر بصوت عال هنا ولكن أليس هذا الخيار الأسوأ؟ عند مقارنة صورتين تم تصديرهما من الفيديو ، فقد فقدت بعض المعلومات منه. أعني ، أنه من السهل حساب التشابه من معلومات برنامج الترميز مما هو عليه من صورتين ، أليس كذلك؟ في الآونة الأخيرة كنت أبحث في بعض الخوارزميات / المكتبات لمقارنة الصور وأنها لا تعمل بشكل جيد كما قد يتطلب واحد. - Samuel
حسنا ، مع ffmpeg يمكنك استخراج الإطارات دون فقدان الجودة باستخدام علم same_quality. إذا كنت تستخدم معلومات codec ، فأنت بحاجة إلى التحقق من أنك لا تحصل على Iframes فقط. على أي حال عملت perl فائدة على ما يرام بالنسبة لي ، وشكلي للغاية. انظر هنا: search.cpan.org/~avif/Image-Compare-0.3/Compare.pm - Eran Ben-Natan


جرب هذا

 ffmpeg -i input.mp4 -vf fps= no_of_thumbs_req/total_video_time out%d.png

باستخدام هذا الأمر ، يمكنني إنشاء العدد المطلوب من الصور المصغرة التي تمثل الفيديو بالكامل.


2
2017-07-31 01:33



لن الصيغة الصحيحة ل fps يكون (no_of_frames_req * fps_of_vid) / total_video_frames؟ - flolilolilo
أنا أبحث عن حل معاكس: حدد المزيد من الإطارات من الفترات التي تكون فيها الكاميرا أكثر ثباتًا ولا تتحرك؟ (حيث يكون الفرق بين الإطارات المتعاقبة أقل ، وليس أعلى). هل هناك طريقة للقيام بذلك؟ - Tina J


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

#!/usr/bin/env bash

## this is slow but gives better thumbnails (takes about 1+ minutes for 20 files)
#-vf thumbnail,scale=640:360 -frames:v 1 poster.png

## this is faster but thumbnails are random (takes about 8 seconds for 20 files)
#-vf scale=640:360 -frames:v 1 poster.png
cd ~/path/to/streams

find . -type f \
  -name "*.m3u8" \
  -execdir sh -c 'ffmpeg -y -i "$0" -vf scale=640:360 -frames:v 1 "poster.png"' \
  {} \;

إذا كنت بحاجة إلى القيام بأكثر من 60 ثانية (الحد من cronjob) ، يمكنك القيام به while حلقة في البرنامج النصي الخاص بك ، وسوف تنفذ إلى الأبد. مجرد إضافة sleep 30 لتغيير التردد إلى 30 ثانية. لا أوصي بتنفيذ ذلك بعدد كبير من مقاطع الفيديو ، نظرًا لأن التشغيل السابق قد لا يكتمل قبل أن يبدأ التشغيل التالي.

من الناحية المثالية مع cronjob أنا فقط تشغيله كل 5 دقائق.


1
2017-12-31 07:03