ฉันจะรับจำนวนเฟรมในวิดีโอบนบรรทัดคำสั่ง linux ได้อย่างไร


30

ฉันมีไฟล์วิดีโอและต้องการรับจำนวนเฟรมวิดีโอที่อยู่ในนั้น ฉันสามารถใช้ffmpegเพื่อรับความยาวของวิดีโอและ FPS อย่างไรก็ตามฉันไม่เห็นสิ่งใดชัดเจนสำหรับจำนวนเฟรมทั้งหมด

ในทางทฤษฎีเราน่าจะสามารถคูณความยาว (เป็นวินาที) โดย FPS เพื่อให้ได้จำนวนเฟรม แต่ในกรณีนี้ความยาว (34.43 วินาที) และ framerate (29.97 fps) ให้ไม่ใช่จำนวนเต็มซึ่งทำให้ฉัน คิดว่าฉันทำอะไรผิด

ฉันต้องสามารถทำสิ่งนี้บนบรรทัดคำสั่งในลักษณะอัตโนมัติและไม่ใช่กราฟิกทั้งหมด ฉันต้องการสิ่งนี้เพื่อให้แน่นอนและไม่ใช่การประเมิน (ถ้าเป็นไปได้กับไฟล์วิดีโอ)

ฉันลองใช้tcprobeกับบางไฟล์ สำหรับไฟล์ AVI บางไฟล์มันใช้งานได้ แต่สำหรับไฟล์ VOB บางไฟล์เอาต์พุต tcprobe ไม่มีจำนวนเฟรม ฉันได้ผลลัพธ์นี้:

[tcprobe] MPEG program stream (PS)
[tcprobe] summary for myfile.vob, (*) = not default, 0 = not detected
import frame size: -g 720x480 [720x576] (*)
     aspect ratio: 4:3 (*)
       frame rate: -f 29.970 [25.000] frc=4 (*)
                   PTS=2199.3972, frame_time=33ms bitrate=7000 kbps
      audio track: -a 0 [0] -e 48000,16,5 [48000,16,2] -n 0x2000 [0x2000] (*)
                   PTS=2199.2763, bitrate=192 kbps
                   -D 3 --av_fine_ms 20 (frames & ms) [0] [0]

สมการของคุณจะให้การประมาณสนามเบสบอลที่ดี เพียงปัดผลลัพธ์ที่ได้ หากคุณต้องการจำนวนเฟรมที่แน่นอนคุณจะต้องตรวจสอบไฟล์โดยตรง - ค่าประมาณของคุณอาจถูกปิดหนึ่งหรือสองทิศทาง
ต้มตุ๋น Quixote

VOB แบบออล - อิน - วันไฟล์หรือดีวีดีสไตล์แบ่งเป็นหลายไฟล์
ต้มตุ๋น Quixote

คำตอบ:


17

นี่เป็นสิ่งที่น่ากลัวและโง่เง่าและเชื่องช้า แต่ดูเหมือนว่าจะได้ผล:

ffmpeg -i foo.avi -vcodec copy -f rawvideo -y /dev/null 2>&1 | tr ^M '\n' | awk '/^frame=/ {print $2}'|tail -n 1

มันจะทำงานได้ดีกับไฟล์ที่ถูกตัดทอนและสตรีมแบบ raw (นั่นคือสาเหตุที่คุณไม่ได้รับอะไรเลยสำหรับไฟล์. vob)


นั่นเป็นสิ่งที่ดีงาม จากประสบการณ์ของฉันมันใช้เวลาไม่นาน ไฟล์ 40 นาทีใช้เวลา <3 วินาทีในการรัน โปรดจำไว้ว่า "^ M" ไม่ใช่ 2 ตัวอักษร ^ และ M คุณต้องกด Control-V แล้วป้อน แทนคำสั่งของคุณฉันใช้: ffmpeg -i somefile.avi -vcodec copy -f rawvideo -y / dev / null 2> & 1 | tr "^ M" '\ n' | grep '^ frame =' | perl -pe 's / ^ frame = \ s * ([0-9] +) \ s. * $ / \ 1 /' | tail -n 1 คำสั่งของคุณล้มเหลวหากไม่มีที่ว่างหลังจาก "frames ="
Rory

1
ใน Ubuntu 12.04, รุ่น ffmpeg Git-2013/04/15-a4f03f0 คุณสามารถละเว้นทั้งสองและ| tr ^M '\n' |tail -n 1นอกจากนี้ยังไม่มีช่องว่างหลังจากframes=ไม่ได้ล้มเหลว (อาจมีการเปลี่ยนแปลงบางอย่างในช่วงสี่ปีที่ผ่านมา)
Camille Goudeseune

สำหรับฉันการกลับมาครั้งนี้มีค่าแตกต่างกันทุกครั้ง
CAMOBAP

1
โซลูชัน Mediainfo ทำงานร่วมกับ VOB .. ฉันอยากจะแนะนำแทน root @ lanparty: / mnt / films # mediainfo --fullscan Bugs_Bunny.vob | grep -i frame \ count จำนวนเฟรม: 175715 จำนวนเฟรม: 183218
kevinf

32

ffprobe สามารถใช้เพื่อรับข้อมูลเกี่ยวกับไฟล์มีเดีย:

ffprobe -select_streams v -show_streams input.avi

คุณจะได้รับรายละเอียดเกี่ยวกับสตรีม:

nb_frames=159697

มองหาnb_framesด้วยgrep:

ffprobe -select_streams v -show_streams input.avi 2>/dev/null | grep nb_frames | sed -e 's/nb_frames=//'

ใช้งานได้กับ avi, mp4 และอื่น ๆ สำหรับบางคอนเทนเนอร์มันไม่แสดงค่าที่ถูกต้องเช่น mpeg

ในกรณีนี้ใช้งานได้ ffprobe -show_packets a.mpg 2>/dev/null | grep video | wc -l


ความคิดที่ดี. ฉันแก้ไขคำสั่งเพียงเล็กน้อยเพื่อให้เลือกสตรีมวิดีโอเท่านั้นและกรองผลลัพธ์ ที่ให้คุณแค่จำนวนเฟรม
slhck

1
ยินดีด้วยสำหรับโซลูชั่นที่ 2 ของคุณที่ทำงานกับ MPEG-2!
malat

1
มันไม่ทำงานกับคอนเทนเนอร์ MKV
Cenk Alti


ดูเหมือนว่าวิธีแรกล้มเหลวในไฟล์ที่เข้ารหัส VBR วิธีที่สองมีความน่าเชื่อถือมากกว่า
Elder Geek

16

ผมโพสต์เกี่ยวกับเรื่องนี้คำถามอื่น การใช้tcprobeเครื่องมือ (จากtranscodeแพ็คเกจ) จำนวนเฟรมรวมอยู่ในข้อมูล ใช้-iสวิตช์เพื่อรับข้อมูลดัมพ์จากไฟล์:

$ tcprobe -i foo.avi
[tcprobe] RIFF data, AVI video
[avilib] V: 29.970 fps, codec=XVID, frames=38630, width=512, height=384
[avilib] A: 48000 Hz, format=0x55, bits=16, channels=2, bitrate=128 kbps,
[avilib]    53707 chunks, 21768720 bytes, VBR
[tcprobe] summary for foo.avi, (*) = not default, 0 = not detected
import frame size: -g 512x384 [720x576] (*)
       frame rate: -f 29.970 [25.000] frc=4 (*)
      audio track: -a 0 [0] -e 48000,16,2 [48000,16,2] -n 0x55 [0x2000] (*)
                   bitrate=128 kbps
           length: 38630 frames, frame_time=33 msec, duration=0:21:28.954

หมายเหตุจำนวนเฟรมถูกกำหนดไว้ที่สองบรรทัดที่นี่


ดูเหมือนว่าจะเป็นคำตอบที่ดีและใช้ได้กับบางไฟล์ แต่สำหรับไฟล์ VOB บางตัวที่ฉันมีฉันไม่มีข้อมูลนั้นในเอาต์พุต ฉันได้อัปเดตคำถามด้วยผลลัพธ์ที่ฉันได้รับ
Rory

ฉันคาดหวัง (แต่ไม่รู้แน่) tcprobe กำลังตรวจสอบส่วนหัวของไฟล์สำหรับข้อมูลนี้ หากไม่รวมอยู่ในส่วนหัว tcprobe อาจไม่พยายามคำนวณ คำถามที่ดี; หวังว่าฉันจะได้คำตอบที่ดีสำหรับคุณ
ต้มตุ๋น quixote

ดูเหมือนจะไม่ทำงานกับไฟล์ที่เข้ารหัส VBR ฉันไม่ได้รับเอาต์พุตจำนวนเฟรม ฉันจะได้รับความละเอียดอัตราส่วนภาพและอัตราเฟรม
Elder Geek

7

ฉันพบว่าใช้mediainfo --fullscan inputfile | grep "Frame count"งานได้ดีกับไฟล์ส่วนใหญ่

ระบบที่ใช้เดเบียนสามารถติดตั้งได้ apt-get install mediainfo

หากคุณได้รับ 2 บรรทัดมากกว่าหนึ่งเอาต์พุตบรรทัดแรกคือแทร็กวิดีโอและบรรทัดที่สองคือแทร็กเสียง ดูเหมือนว่าสิ่งนี้จะเกิดขึ้นกับไฟล์ที่มีเสียง Variable Bit Rate

ทดสอบใน. mkv, .m4v, .mp4, flv, vob และตัวอย่าง. avi ณ วันที่แก้ไข

แหล่งที่มา: วิธีการดึงข้อมูลไฟล์วิดีโอจากบรรทัดคำสั่งภายใต้ Linux? และการทดสอบภายใต้รสชาติของอูบุนตู

คุณสามารถค้นหา mediainfo สำหรับระบบปฏิบัติการของคุณได้ที่นี่


4

ffprobe -select_streams v -show_frames -count_frames INPUT_FILE | grep pkt_duration_time =

เพิ่มระยะเวลา อาจเป็นนักเล่นด้วย sed / awk และสิ่งที่ไม่

จากการทดสอบของฉันฉันสามารถพูดได้ว่าตอนนี้มันได้แสดงให้เห็นว่าเป็นที่น่าเชื่อถือที่สุด คุณจะได้รับปริมาณที่แน่นอนและระยะเวลาที่แน่นอน แม้จะมีอัตราเฟรมที่หลากหลายซึ่งเครื่องมืออื่น ๆ เช่น mediainfo ก็ดูเหมือนจะไม่สนใจ


3

ฉันพบว่าจำนวนเฟรมเป็นสองเท่าของระยะเวลาเฟรมต่อวินาที (ไม่รู้เลยว่าทำไมฉันถึงมีความสุข)

ในสคริปต์ของฉันฉันมี:

# Get duration and fps
duration=$($FFMPEG -i $input 2>&1 | sed -n "s/.* Duration: \([^,]*\), start: .*/\1/p")
fps=$($FFMPEG -i $input 2>&1 | sed -n "s/.*, \(.*\) tb.*/\1/p")

hours=$(echo $duration | cut -d":" -f1)
minutes=$(echo $duration | cut -d":" -f2)
seconds=$(echo $duration | cut -d":" -f3)
# For some reason, we have to multiply by two (no idea why...)
# Get the integer part with cut
frames=$(echo "($hours*3600+$minutes*60+$seconds)*$fps*2" | bc | cut -d"." -f1)

และใช่ด้วยเหตุผลบางอย่างฉันต้องได้ส่วนจำนวนเต็มของมัน มันไม่สมเหตุสมผล แต่สคริปต์นี้สามารถแปลงวิดีโอของฉันได้อย่างถูกต้องจนถึงตอนนี้


เนื่องจาก FPS ย่อมาจาก Frames Per Second (หรือนักกีฬาคนแรก: D) และหากมี 30 FPS เพียงแค่คูณด้วยจำนวนวินาทีในวิดีโอ
John T

ใช่จอห์นฉันหาได้ แต่ไม่ได้อธิบายว่าทำไมฉันต้องคูณด้วย 2 เพื่อให้ได้จำนวนเฟรมที่ถูกต้อง ... ในกรณีของฉันหลังจากที่ฉันคำนวณจำนวนเฟรมฉันเปิด ffmpeg ใน พื้นหลังและวิเคราะห์บันทึกเพื่อสร้างแถบความคืบหน้า บันทึกแสดงจำนวนเฟรมที่ส่งผ่านในการแปลง เมื่อวิดีโอทั้งหมดถูกแปลงเฟรม # ก็เป็น int (วินาที * fps * 2) ดังนั้นโค้ดของฉัน แต่ฉันอยากจะรู้ว่าทำไม ;-)
inkaphink

ที่อยากรู้อยากเห็น; tcprobeผลลัพธ์ในคำตอบของฉันให้ # ของเฟรมเป็นว่าวินาที * เฟรมต่อวินาที (ถึงโค้งมน) ฉันคาดหวังว่าคุณจะเห็น ffmpeg แปลกตา คุณได้ลองวิเคราะห์ไฟล์ด้วยเครื่องมืออื่น ๆ เพื่อดูว่ามันแสดงจำนวนเฟรมเท่ากันหรือไม่?
ต้มตุ๋น Quixote

อืม ... น่าสนใจ ฉันพยายามวิดีโอและฉันได้และseconds*fps=1001.59 tcprobe=1002เห็นได้ชัดtcprobeว่าบอกฉันว่าฉันไม่จำเป็นต้องคูณสอง ทำไม ffmpeg ให้ตัวเลขที่ใหญ่เป็นสองเท่าในบันทึกเมื่อมันทำการแปลง
ℝaphink

2
มันเป็นภาพพัวพัน? ถ้ามีสองฟิลด์ต่อเฟรมและมันอาจทำให้คุณมีจำนวนฟิลด์
stib

3

ทดสอบบน Ubuntu

melt icecap.mp4 -consumer xml
  • melt- การหลอมถูกใช้เป็นเครื่องมือทดสอบสำหรับเฟรมเวิร์ก MLT แต่มันก็เป็นเครื่องมือแก้ไขวิดีโอที่เน้นบรรทัดคำสั่งแบบมัลติทาสก์อันทรงพลัง มันยังสามารถใช้เป็นเครื่องเล่นสื่อเรียบง่ายสำหรับไฟล์เสียงและวิดีโอ

  • -consumerid [: arg] [name = value] *
    ตั้งค่าคอนซูเมอร์ (ซิงค์)

  • xml - ตั้งค่าคอนซูเมอร์ (ซิงค์) ไปยังเอาต์พุตที่จัดรูปแบบ xml

  • <property name="length">nnnn</property>- แสดงจำนวนเฟรมที่nnnnจะถูกแทนที่ด้วยตัวเลขจำนวนเต็มซึ่งเท่ากับจำนวนเฟรม

หากคุณยังไม่ละลายคุณสามารถติดตั้งบน Ubuntu และระบบอื่น ๆ ที่ใช้ Debian sudo apt-get install melt


1
สั้นมากคุณต้องการที่จะขยายในสิ่งที่มันทำทำไมมันทำงาน ฯลฯ
เดวิด

นี้ทำงานได้ดีกับไฟล์ mp4 h264 ซึ่งไม่ได้ให้ framecount mediainfo -fullscan filenameผ่าน
ผู้สูงอายุ Geek

3

โดยตรงกับmediainfoไม่มี grep ไม่ต้องรอไม่มีอะไร:

mediainfo --Inform='Video;%FrameCount%' $the_file

สำหรับข้อมูลอื่น ๆ ดู mediainfo --info-parameters


0

คุณสามารถทำได้โดยการเพิ่มและคูณค่าที่คุณได้รับจาก ffprobe

หมายเหตุ: ffprobe เป็นส่วนหนึ่งของ libav (avconv) - รุ่น linux ของ ffmpeg

#your command -
 ffprobe man.avi

เมื่อคุณทำเช่นนี้คุณจะได้รับจำนวนเฟรมต่อ / วินาทีและระยะเวลาของคลิป

แปลงระยะเวลาของคลิปเป็นวินาทีและคูณค่านั้นด้วยจำนวนเฟรม / วินาที

อย่าลืมปัดเศษตัวเลขให้ใกล้เคียงที่สุด


บน Ubuntu 14.04 LTS ffprobeไม่พร้อมใช้งาน แต่มีสิ่งที่เรียกว่าavprobeในlibav-tools(ซึ่งยังให้avconv) แต่ที่ด้านข้างของฉันมันไม่ได้พิมพ์จำนวนเฟรมใด ๆ อย่างน้อยก็ไม่ได้สำหรับรูปแบบที่ฉันได้ลอง มันเป็นเพียงแค่พิมพ์สิ่งที่avprobe -iพิมพ์ด้วยและนี่เป็นเพียงบางชิ้นเล็ก ๆ น้อย ๆ เกี่ยวกับรูปแบบเศร้า แม้จะมี-v debugเพียงบอกคุณสมบัติที่ดีของฮาร์ดแวร์และซอฟต์แวร์ของฉันที่ติดตั้ง แต่ไม่ใช่ข้อมูลที่น่าสนใจเกี่ยวกับไฟล์ / สตรีมเพื่อสอบสวน บางทีมันอาจซ่อนอยู่ในตัวเลือกมากมายที่มีให้เลือก ใครจะรู้?
Tino

@Tino ffprobe มีให้บริการเป็นส่วนหนึ่งของแพ็คเกจ ffmpeg avconv เป็นทางแยกของ ffmpeg และทำให้เกิดความสับสน ดู: stackoverflow.com/questions/9477115/…
ผู้สูงอายุ Geek

@ElderGeek สำหรับ Ubuntu 14.04 LTS ไม่มีffmpegในที่เก็บอย่างเป็นทางการ ลิงก์ที่คุณระบุอย่างถูกต้องระบุ: FFmpeg ส่งคืนใน Ubuntu 15.04 "Vivid Vervet" . อย่างไรก็ตามสถานการณ์ตอนนี้เปลี่ยนไปเนื่องจาก 16.04 LTS หมดแล้ว
Tino

@Tino นั่นคือความจริง อย่างไรก็ตามฉันจะไม่ถือเอาว่าไม่มีอยู่ในที่เก็บ คุณจะสังเกตเห็นว่ามันมีไว้สำหรับ Trusty (14.04) ที่นี่: ffmpeg.org/download.html
Elder Geek

0

ลินุกซ์

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

ทับทิม

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

-2

วิธีที่ดีที่สุด: (โดยตรงโดยการคำนวณพารามิเตอร์ที่ถูกต้องยืนยันโดย ffmpeg)

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"

ผลลัพธ์ ->

r_frame_rate=24000/1001
duration=8177.794625

การคำนวณ ->

Frames=24000/1001*8177.794625=196071 (exactly... ;P)

หลักฐาน ->

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
shareeditdeleteflag

ฉันได้r_frame_rate = 25/1 ระยะเวลา = N / A
Elder Geek
โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.