Ambil jumlah bingkai dengan ffmpeg

112

Apakah ada yang tahu cara mengambil jumlah total frame dari file video menggunakan ffmpeg? Output render dari ffmpeg menunjukkan frame saat ini dan saya membutuhkan jumlah frame untuk menghitung kemajuan dalam persen.

Hansl
sumber
1
superuser.com/questions/84631/…
Ciro Santilli 郝海东 冠状 病 六四 事件 法轮功

Jawaban:

158

Catatan: Adanya daftar edit di MP4 / M4V / M4A / MOV dapat mempengaruhi nomor bingkai Anda. Lihat Mengedit daftar di bawah.


ffprobe: Membuat kueri penampung

ffprobe -v error -select_streams v:0 -show_entries stream=nb_frames -of default=nokey=1:noprint_wrappers=1 input.mp4
  • Ini adalah metode yang cepat.
  • Tidak semua format (seperti Matroska) akan melaporkan jumlah frame yang dihasilkan N/A. Lihat metode lain yang tercantum di bawah ini.

ffprobe: Hitung jumlah frame

ffprobe -v error -count_frames -select_streams v:0 -show_entries stream=nb_read_frames -of default=nokey=1:noprint_wrappers=1 input.mkv
  • Ini adalah metode yang lambat.
  • Tambahkan -skip_frame nokeyopsi untuk hanya menghitung bingkai kunci.

ffmpeg: Hitung jumlah frame

Jika Anda tidak memiliki ffprobeAnda dapat menggunakan ffmpegsebagai gantinya:

ffmpeg -i input.mkv -map 0:v:0 -c copy -f null -
  • Ini adalah metode yang agak cepat.
  • Lihat di frame=dekat akhir keluaran konsol.
  • Tambahkan -discard nokeyopsi input (sebelum -i) untuk hanya menghitung bingkai kunci.

Edit daftar

Abaikan daftar edit MP4 / M4V / M4A / MOV dengan -ignore_editlist 1opsi input. Defaultnya adalah tidak mengabaikan daftar edit.

Apa arti dari opsi ffprobe

  • -v error Ini menyembunyikan keluaran "info" (info versi, dll) yang membuat parsing lebih mudah.

  • -count_frames Hitung jumlah bingkai per aliran dan laporkan di bagian aliran yang sesuai.

  • -select_streams v:0 Pilih hanya aliran video.

  • -show_entries stream=nb_framesatau Hanya -show_entries stream=nb_read_framestampilkan entri untuk nb_framesatau nb_read_frames.

  • -of default=nokey=1:noprint_wrappers=1Tetapkan format keluaran (alias "penulis") ke default, jangan cetak kunci dari setiap bidang ( nokey=1), dan jangan cetak header dan footer bagian ( noprint_wrappers=1). Ada alternatif yang lebih pendek seperti -of csv=p=0.

Lihat juga


mediainfo

mediainfoAlat terkenal dapat menghasilkan jumlah bingkai:

mediainfo --Output="Video;%FrameCount%" input.avi

MP4Box

Untuk file MP4 / M4V / M4A.

MP4Box dari gpac dapat menunjukkan jumlah frame:

MP4Box -info input.mp4

Lihat Media Infobaris di keluaran untuk aliran video yang dimaksud:

Media Info: Language "Undetermined (und)" - Type "vide:avc1" - 2525 samples

Dalam contoh ini, aliran video memiliki 2525 bingkai.


boxdumper

Untuk file MP4 / M4V / M4A / MOV.

boxdumperadalah alat sederhana dari l-smash. Ini akan menghasilkan sejumlah besar informasi. Di bawah bagian stszkotak ukuran sampel mengacu sample_countpada jumlah bingkai. Dalam contoh ini, input memiliki 1900 bingkai video:

boxdumper input.mp4
  ...
  [stsz: Sample Size Box]
    position = 342641
    size = 7620
    version = 0
    flags = 0x000000
    sample_size = 0 (variable)
    sample_count = 1900
  • Ketahuilah bahwa file mungkin memiliki lebih dari satu stszatom.
llogan
sumber
5
Atau, jika Anda menginginkan kecepatan lebih dan jika nb_frames cukup andal, sederhanakan sebagai:ffprobe -v error -select_streams v:0 -show_entries stream=nb_frames -of default=nokey=1:noprint_wrappers=1 input.mkv
juanitogan
Ini mengeluarkan jawaban dua kali untuk saya (yaitu 2600 \ n 2600). Adakah alasan khusus yang akan terjadi?
jbodily
@jbodily Contoh atau juanitogan saya? Saya juga tidak dapat menduplikasinya. Tidak banyak yang bisa dikerjakan di sini.
llogan
+1, paling tidak karena, tidak seperti terlalu banyak jawaban lain tentang alat baris perintah mana pun, yang satu ini sebenarnya menjelaskan semua opsi baris perintah. Terima kasih.
Ray
1
Perhatikan bahwa opsi pertama, kueri penampung, sebenarnya memproses file karena count_frames. Lihat komentar @ juanitogan.
aggieNick02
23

Di Unix, ini berfungsi seperti pesona:

ffmpeg -i 00000.avi -vcodec copy -acodec copy -f null /dev/null 2>&1 | grep 'frame=' | cut -f 2 -d ' '
ataraxic
sumber
3
Sangat bagus. Hanya Anda tidak perlu menyalin aliran audio. Anda dapat menggunakan -an instat.
rekire
1
@PrakharMohanSrivastava Periksa jawaban ini
Antonio
4
Sebenarnya, ini tampaknya cepat dan dapat diandalkan:ffmpeg -i 00000.avi -map 0:v:0 -c copy -f null -y /dev/null 2>&1 | grep -Eo 'frame= *[0-9]+ *' | grep -Eo '[0-9]+' | tail -1
Timothy Zorn
1
@Michael terima kasih atas senyum dengan kopi pagi saya :-)
Lloyd Moore
1
@TimothyZorn Anda membuat hari saya!
Mladen Danic
13

Hitunglah berdasarkan waktu.

Itulah yang saya lakukan dan itu bekerja sangat baik untuk saya, dan banyak lainnya.) Pertama, temukan panjang video di cuplikan di bawah ini:

Seems stream 0 codec frame rate differs from container frame rate: 5994.00 
(5994/1) -> 29.97 (30000/1001)
Input #0, mov,mp4,m4a,3gp,3g2,mj2, from '/Users/stu/Movies/District9.mov':
  Duration: 00:02:32.20, start: 0.000000, bitrate: 9808 kb/s
    Stream #0.0(eng): Video: h264, yuv420p, 1920x1056, 29.97tbr, 2997tbn, 5994tbc
    Stream #0.1(eng): Audio: aac, 44100 Hz, 2 channels, s16
    Stream #0.2(eng): Data: tmcd / 0x64636D74

Anda harus dapat menemukan secara konsisten dan aman Duration: hh:mm:ss.nnuntuk menentukan ukuran klip video sumber. Kemudian, untuk setiap baris pembaruan (CR, tanpa LF) Anda dapat mengurai teks untuk tanda waktu saat ini di:

frame=   84 fps= 18 q=10.0 size=       5kB time=1.68 bitrate=  26.1kbits/s    
frame=   90 fps= 17 q=10.0 size=       6kB time=1.92 bitrate=  23.8kbits/s    
frame=   94 fps= 16 q=10.0 size=     232kB time=2.08 bitrate= 913.0kbits/s    

Berhati-hatilah untuk tidak selalu mengharapkan hasil yang sempurna dari baris status ini. Mereka dapat menyertakan pesan kesalahan seperti di sini:

frame=   24 fps= 24 q=-1.0 size=       0kB time=1.42 bitrate=   0.3kbits/s    
frame=   41 fps= 26 q=-1.0 size=       0kB time=2.41 bitrate=   0.2kbits/s    
[h264 @ 0x1013000]Cannot parallelize deblocking type 1, decoding such frames in
sequential order
frame=   49 fps= 24 q=26.0 size=       4kB time=0.28 bitrate= 118.1kbits/s    
frame=   56 fps= 22 q=23.0 size=       4kB time=0.56 bitrate=  62.9kbits/s    

Setelah Anda punya waktu, itu adalah matematika sederhana: time / durration * 100 = % done.

Stu Thompson
sumber
1
Maaf saya bodoh tapi bagaimana saya bisa melakukan waktu / durasi ketika durasi dalam format jj: mm: ss.nn dan waktu selalu dalam format xx.yy?
Omar Ali
2
@Omar, Sebagai pengembang .NET, yang saya lakukan adalah membuat TimeSpandarinya, lalu menggunakan currentDurationTimeSpan.Ticks / (totalDurationTimeSpan.Ticks / 100). TimeSpan juga menyediakan fungsi Parse yang kuat, lihatlah
Shimmy Weitzhandler
solusi terbaik, waktu saya dalam hh: mm: ss: ms jadi saya kira dalam 3 tahun ini FFMPEG meningkatkan format waktu keluaran.
ElektroStudios
1
Perhatikan bahwa output konsol mungkin mengatakan 29,97, tapi itu kependekan dari 30000/1001. Sama untuk 23,98 yaitu 24000/1001 dan 59,94 adalah 60000/1001.
llogan
Sebagai catatan, ini tidak berfungsi untuk video dengan frekuensi gambar variabel (jelas).
Timothy Zorn
8

Tidak semua format menyimpan jumlah bingkai atau durasi totalnya - dan meskipun demikian, file mungkin tidak lengkap - jadi ffmpeg tidak mendeteksi salah satu dari keduanya secara akurat secara default.

Sebaliknya, coba cari di akhir file dan baca waktu, lalu hitung waktu saat ini sambil pergi.

Atau, Anda dapat mencoba AVFormatContext->nb_index_entriesatau durasi yang terdeteksi, yang seharusnya bekerja dengan baik setidaknya pada AVI / MOV yang tidak rusak, atau perpustakaan FFMS2, yang mungkin terlalu lambat untuk mengganggu bilah kemajuan.

alex aneh
sumber
8

Cobalah sesuatu seperti:

ffmpeg -i "path to file" -f null /dev/null

Ini menulis nomor bingkai ke stderr, sehingga Anda dapat mengambil bingkai terakhir dari ini.

a1kmm
sumber
8

Anda dapat menggunakan ffprobe untuk mendapatkan nomor bingkai dengan perintah berikut

  1. metode pertama

ffprobe.exe -i video_name -print_format json -loglevel fatal -show_streams -count_frames -select_streams v

yang memberitahu untuk mencetak data json format

select_streams vakan memberi tahu kami ffprobeuntuk memberi kami videodata streaming dan jika Anda menghapusnya, itu akan memberi Andaaudio informasi juga

dan hasilnya akan seperti

{
    "streams": [
        {
            "index": 0,
            "codec_name": "mpeg4",
            "codec_long_name": "MPEG-4 part 2",
            "profile": "Simple Profile",
            "codec_type": "video",
            "codec_time_base": "1/25",
            "codec_tag_string": "mp4v",
            "codec_tag": "0x7634706d",
            "width": 640,
            "height": 480,
            "coded_width": 640,
            "coded_height": 480,
            "has_b_frames": 1,
            "sample_aspect_ratio": "1:1",
            "display_aspect_ratio": "4:3",
            "pix_fmt": "yuv420p",
            "level": 1,
            "chroma_location": "left",
            "refs": 1,
            "quarter_sample": "0",
            "divx_packed": "0",
            "r_frame_rate": "10/1",
            "avg_frame_rate": "10/1",
            "time_base": "1/3000",
            "start_pts": 0,
            "start_time": "0:00:00.000000",
            "duration_ts": 256500,
            "duration": "0:01:25.500000",
            "bit_rate": "261.816000 Kbit/s",
            "nb_frames": "855",
            "nb_read_frames": "855",
            "disposition": {
                "default": 1,
                "dub": 0,
                "original": 0,
                "comment": 0,
                "lyrics": 0,
                "karaoke": 0,
                "forced": 0,
                "hearing_impaired": 0,
                "visual_impaired": 0,
                "clean_effects": 0,
                "attached_pic": 0
            },
            "tags": {
                "creation_time": "2005-10-17 22:54:33",
                "language": "eng",
                "handler_name": "Apple Video Media Handler",
                "encoder": "3ivx D4 4.5.1"
            }
        }
    ]
}

2. Anda dapat menggunakan

ffprobe -v error -show_format -show_streams video_name

yang akan memberi Anda data streaming, jika Anda ingin informasi yang dipilih seperti kecepatan bingkai, gunakan perintah berikut

ffprobe -v error -select_streams v:0 -show_entries stream=avg_frame_rate -of default=noprint_wrappers=1:nokey=1 video_name

yang memberikan angka berdasarkan informasi video Anda, masalahnya adalah ketika Anda menggunakan metode ini, kemungkinan Anda mendapatkan file N/A sebagai output.

untuk informasi lebih lanjut periksa halaman ini FFProbe Tips

Hadi Rasekh
sumber
4

coba ini:

ffmpeg -i "path to file" -f null /dev/null 2>&1 | grep 'frame=' | cut -f 2 -d ' '
Julien
sumber
Tidak bekerja dengan *.ts. Outputnya adalah baris kosong.
Victor Polevoy
3

Karena komentar saya mendapat beberapa suara positif, saya pikir saya akan meninggalkannya sebagai jawaban:

ffmpeg -i 00000.avi -map 0:v:0 -c copy -f null -y /dev/null 2>&1 | grep -Eo 'frame= *[0-9]+ *' | grep -Eo '[0-9]+' | tail -1

Ini harus cepat, karena tidak ada pengkodean yang dilakukan. ffmpeghanya akan mendemux file dan membaca (mendekode) aliran video pertama secepat mungkin. grepPerintah pertama akan mengambil teks yang menunjukkan bingkai. grepPerintah kedua hanya akan mengambil nomor dari itu. The tailperintah hanya akan menunjukkan garis akhir (jumlah bingkai akhir).

Timothy Zorn
sumber
2

untuk membangun jawaban siswa. inilah cara saya menemukan frekuensi gambar untuk video dari ponsel saya. saya menjalankan perintah berikut untuk sementara waktu. saya membiarkan jumlah frame naik menjadi sekitar ~ 10.000 sebelum saya menjadi tidak sabar dan menekan ^ C:

$ ffmpeg -i 2013-07-07\ 12.00.59.mp4 -f null /dev/null 2>&1
...
Press [q] to stop, [?] for help
[null @ 0x7fcc80836000] Encoder did not produce proper pts, making some up.
frame= 7989 fps= 92 q=0.0 Lsize=N/A time=00:04:26.30 bitrate=N/A dup=10 drop=0    
video:749kB audio:49828kB subtitle:0 global headers:0kB muxing overhead -100.000042%
Received signal 2: terminating.
$

kemudian, saya mengambil dua informasi dari baris itu yang dimulai dengan "frame =", jumlah frame, 7989, dan waktu, 00: 04: 26.30. Pertama-tama Anda harus mengubah waktu menjadi detik dan kemudian membagi jumlah bingkai dengan detik untuk mendapatkan "bingkai per detik". "frame per second" adalah frekuensi gambar Anda.

$ bc -l
0*60*60 + 4*60 + 26.3
266.3

7989/(4*60+26.3)
30.00000000000000000000
$

framerate untuk video saya adalah 30 fps.

margaret
sumber
2

Satu-satunya akurasi yang dapat saya lakukan adalah sebagai berikut:

ffprobe -i my_video.mp4 -show_frames 2>&1|grep -c '^\[FRAME'

Untuk memastikan ini berfungsi dengan video:

ffprobe -i my_video.mp4 -show_frames 2>&1 | grep -c media_type=video
Lloyd Moore
sumber
Saya memberi suara positif pada jawaban Anda, tetapi itu hanya akan berfungsi jika video tidak berisi audio. Jika memang mengandung, yang ini akan berfungsi:ffprobe -i my_video.mp4 -show_frames 2>&1 | grep -c media_type=video
Gobe
2

Maaf untuk jawaban necro, tapi mungkin akan membutuhkan ini (karena saya tidak menemukan solusi untuk rilis ffmpeg terbaru.

Dengan ffmpeg 3.3.4 saya menemukan seseorang dapat menemukannya dengan yang berikut:

ffprobe -i video.mp4 -show_streams -hide_banner | grep "nb_frames"

Pada akhirnya itu akan menghasilkan jumlah bingkai. Ini bekerja untuk saya pada video dengan audio. Ini memberikan dua kali baris "nb_frames", tetapi baris pertama adalah jumlah frame sebenarnya pada video yang saya uji.

acidrums4
sumber
Terima kasih @ acidrums4. Diverifikasi, metode ini berfungsi dengan versi terbaru dari github yang saya buat hari ini.
Paul J
1

Saya menggunakan php_ffmpeg maka saya bisa mendapatkan semua waktu dan semua frame film. Sebagai berikut

$input_file='/home/strone/workspace/play/CI/abc.rmvb';
$ffmpegObj = new ffmpeg_movie($input_file);
echo $ffmpegObj->getDuration();
    echo $ffmpegObj->getFrameCount();

Dan kemudian detailnya ada di halaman.

http://ffmpeg-php.sourceforge.net/doc/api/ffmpeg_movie.php

xingyue
sumber
1
Cmd ->

ffprobe.exe -v error -select_streams v:0 -show_entries stream=r_frame_rate,duration -of default=nw=1 "d:\movies\The.Matrix.1999.1080p.BrRip.x264.YIFY.dut.mp4"

Result ->

r_frame_rate=24000/1001
duration=8177.794625

Calculation ->

Frames=24000/1001*8177.794625=196071

Proof -> 

ffmpeg -i "d:\movies\The.Matrix.1999.1080p.BrRip.x264.YIFY.dut.mp4" -f null /dev/null
ffmpeg version N-92938-g0aaaca25e0-ffmpeg-windows-pacman Copyright (c) 2000-2019 the FFmpeg developers
  built with gcc 8.2.0 (GCC)
  configuration: --pkg-config=pkg-config --pkg-config-flags=--static --extra-version=ffmpeg-windows-pacman --enable-version3 --disable-debug --disable-w32threads --arch=x86_64 --target-os=mingw32 --cross-prefix=/opt/sandbox/cross_compilers/mingw-w64-x86_64/bin/x86_64-w64-mingw32- --enable-libcaca --enable-gray --enable-libtesseract --enable-fontconfig --enable-gmp --enable-gnutls --enable-libass --enable-libbluray --enable-libbs2b --enable-libflite --enable-libfreetype --enable-libfribidi --enable-libgme --enable-libgsm --enable-libilbc --enable-libmodplug --enable-libmp3lame --enable-libopencore-amrnb --enable-libopencore-amrwb --enable-libopus --enable-libsnappy --enable-libsoxr --enable-libspeex --enable-libtheora --enable-libtwolame --enable-libvo-amrwbenc --enable-libvorbis --enable-libvpx --enable-libwebp --enable-libzimg --enable-libzvbi --enable-libmysofa --enable-libaom --enable-libopenjpeg --enable-libopenh264 --enable-liblensfun --enable-nvenc --enable-nvdec --extra-libs=-lm --extra-libs=-lpthread --extra-cflags=-DLIBTWOLAME_STATIC --extra-cflags=-DMODPLUG_STATIC --extra-cflags=-DCACA_STATIC --enable-amf --enable-libmfx --enable-gpl --enable-avisynth --enable-frei0r --enable-filter=frei0r --enable-librubberband --enable-libvidstab --enable-libx264 --enable-libx265 --enable-libxvid --enable-libxavs --enable-avresample --extra-cflags='-march=core2' --extra-cflags=-O2 --enable-static --disable-shared --prefix=/opt/sandbox/cross_compilers/mingw-w64-x86_64/x86_64-w64-mingw32 --enable-nonfree --enable-decklink --enable-libfdk-aac
  libavutil      56. 25.100 / 56. 25.100
  libavcodec     58. 43.100 / 58. 43.100
  libavformat    58. 25.100 / 58. 25.100
  libavdevice    58.  6.101 / 58.  6.101
  libavfilter     7. 47.100 /  7. 47.100
  libavresample   4.  0.  0 /  4.  0.  0
  libswscale      5.  4.100 /  5.  4.100
  libswresample   3.  4.100 /  3.  4.100
  libpostproc    55.  4.100 / 55.  4.100
Input #0, mov,mp4,m4a,3gp,3g2,mj2, from 'd:\movies\The.Matrix.1999.1080p.BrRip.x264.YIFY.dut.mp4':
  Metadata:
    major_brand     : isom
    minor_version   : 512
    compatible_brands: isomiso2avc1mp41
    encoder         : Lavf58.25.100
  Duration: 02:16:17.91, start: 0.000000, bitrate: 2497 kb/s
    Stream #0:0(und): Video: h264 (High) (avc1 / 0x31637661), yuv420p, 1920x800 [SAR 1:1 DAR 12:5], 2397 kb/s, 23.98 fps, 23.98 tbr, 24k tbn, 47.95 tbc (default)
    Metadata:
      handler_name    : VideoHandler
    Stream #0:1(und): Audio: aac (LC) (mp4a / 0x6134706D), 44100 Hz, stereo, fltp, 93 kb/s (default)
    Metadata:
      handler_name    : GPAC ISO Audio Handler
Stream mapping:
  Stream #0:0 -> #0:0 (h264 (native) -> wrapped_avframe (native))
  Stream #0:1 -> #0:1 (aac (native) -> pcm_s16le (native))
Press [q] to stop, [?] for help
Output #0, null, to '/dev/null':
  Metadata:
    major_brand     : isom
    minor_version   : 512
    compatible_brands: isomiso2avc1mp41
    encoder         : Lavf58.25.100
    Stream #0:0(und): Video: wrapped_avframe, yuv420p, 1920x800 [SAR 1:1 DAR 12:5], q=2-31, 200 kb/s, 23.98 fps, 23.98 tbn, 23.98 tbc (default)
    Metadata:
      handler_name    : VideoHandler
      encoder         : Lavc58.43.100 wrapped_avframe
    Stream #0:1(und): Audio: pcm_s16le, 44100 Hz, stereo, s16, 1411 kb/s (default)
    Metadata:
      handler_name    : GPAC ISO Audio Handler
      encoder         : Lavc58.43.100 pcm_s16le
frame=196071 fps=331 q=-0.0 Lsize=N/A time=02:16:17.90 bitrate=N/A speed=13.8x
video:102631kB audio:1408772kB subtitle:0kB other streams:0kB global headers:0kB muxing overhead: unknown
Gerard Wensink
sumber
Framerate biasanya dihitung dari dua parameter. r_frame_rate = 24000/1001 (= 23,97602397602397 ...) Dibulatkan oleh ffmpeg ke: 23,98 Durasi = jam * 3600 + menit * 60 + detik. sisa = 8177,91 Sementara parameter durasi = 8177,794625 Tetapi Bingkai = 24000/1001 * 8177,794625 = 196071 memberikan jumlah pasti dari frame. (Tidak bercanda).
Gerard Wensink
0

linux

ffmpeg -i "/home/iorigins/Завантаження/123.mov" -f null /dev/null

rubi

result = `ffmpeg -i #{path} -f null - 2>&1`
r = result.match("frame=([0-9]+)")
p r[1]
Yaroslav Malyk
sumber