วิธีการแยกหนึ่งเฟรมของวิดีโอทุก ๆ N วินาทีให้กับรูปภาพ?


71

ฉันจะแปลงไฟล์วิดีโอเป็นลำดับภาพได้อย่างไรเช่นหนึ่งเฟรมทุก ๆ N วินาที mplayer หรือ ffmpeg สามารถทำสิ่งนี้ได้หรือไม่? ฉันใช้ MPlayer เพื่อจับภาพหน้าจอด้วยตนเอง แต่ฉันต้องการทำให้เป็นแบบอัตโนมัติสำหรับวิดีโอขนาดยาว


ดูคำถามที่เกี่ยวข้องกับการเลือกคุณภาพของภาพ: stackoverflow.com/questions/10225403/…
Pierz

คำตอบ:


70

มันง่ายมากกับ ffmpeg และสามารถส่งออกหนึ่งเฟรมทุก ๆ N วินาทีโดยไม่ต้องใช้สคริปต์เพิ่มเติม หากต้องการส่งออกเป็นลำดับภาพให้ใช้myimage_%04d.pngหรือคล้ายกับเอาต์พุต %0xdบิตจะถูกแปลงเป็นศูนย์เบาะจำนวนเต็มxตัวเลขยาว - ตัวอย่างฉันให้ได้รับการส่งออกเป็น

  • myimage_0000.png,
  • myimage_0001.png,
  • myimage_0002.png

    ฯลฯ ..

คุณสามารถใช้รูปแบบภาพนิ่งมากมาย png, jpeg, tga หรืออะไรก็ได้ (ดูffmpeg -formatsรายการทั้งหมด)

ตกลงตอนนี้เรารู้วิธีส่งออกภาพยนตร์เป็นลำดับรูปภาพ แต่บอกว่าเราไม่ต้องการส่งออกทุกเฟรมใช่ไหม

เคล็ดลับคือเพียงแค่เปลี่ยนอัตราเฟรมของเอาต์พุตเป็นสิ่งที่เราต้องการโดยใช้-r nตัวเลือกที่nมีจำนวนเฟรมต่อวินาที 1 เฟรมต่อวินาทีจะเป็น-r 1หนึ่งเฟรมทุก ๆ สี่วินาทีจะเป็น-r 0.25หนึ่งเฟรมทุก ๆ สิบวินาทีจะเป็น-r 0.1เช่นนั้น

เพื่อที่จะนำมันทั้งหมดเข้าด้วยกันนี้เป็นวิธีที่มันจะมีลักษณะที่จะบันทึกหนึ่งเฟรมของinput.movทุกสี่วินาทีoutput_0000.png, output_0001.pngฯลฯ .:

ffmpeg -i input.mov -r 0.25 output_%04d.png

โปรดทราบว่า-r 0.25ตัวเลือกที่จะไปหลังจาก-i input.movส่วนหนึ่งเพราะการควบคุมอัตราเฟรมของเอาท์พุท หากคุณใส่ไว้ก่อนหน้าอินพุตจะถือว่าไฟล์อินพุตราวกับว่ามีอัตราเฟรมที่ระบุ

เปลี่ยน XD% ถึงตัวเลขอย่างไรก็ดีหลายคนที่คุณต้องการเช่นถ้าคำสั่งจะสร้างมากกว่า 10,000 เฟรมเปลี่ยนไป%04d %05dยังใช้งานได้กับไฟล์อินพุตที่เป็นลำดับภาพ อ่านเพิ่มเติมที่นี่

ผู้ใช้ Windows : ในการใช้บรรทัดคำสั่ง%

ตัวอย่าง: ffmpeg -i inputFile.mp4 -r 1 outputFile_%02d.png

ใน CMD และ BAT Scripts ใช้ %%

ตัวอย่าง: ffmpeg -i inputFile.mp4 -r 1 outputFile %%02d.png

ดังนั้นสองครั้ง%%ในสคริปต์และเดี่ยว%ในบรรทัดคำสั่งแบบโต้ตอบ ทำให้มันผิดในสถานการณ์ใดสถานการณ์หนึ่งจะสร้างข้อผิดพลาด


ฉันควรใส่อะไร-rถ้าฉันต้องการส่งออกทุกเฟรม ถ้าฉันรู้ FPS ของวิดีโอฉันเดาว่าฉันป้อนข้อมูลนั้น แต่ถ้าฉันไม่ทำล่ะ
Tomáš Zato

4
อย่าใช้แฟล็ก -r เลย จากนั้น FFMPEG จะใช้อัตราเฟรมของไฟล์อินพุต
stib

2
โปรดทราบว่าคุณจะได้จริงๆต้องการที่จะใช้jpegsสำหรับการนี้เว้นแต่คุณจะแน่ใจpng's เป็นสิ่งที่คุณต้องการ ในกรณีของฉันjpegแต่ละอันมีขนาดประมาณ 50kb และpngประมาณ 2MB
mlissner

5
ข้อได้เปรียบของ pngs คือการบีบอัดแบบไม่สูญเสียข้อมูลดังนั้นหากคุณใช้ลำดับภาพเป็นสื่อกลางและไม่คำนึงถึงขนาดพิเศษนั่นคือเวลาที่คุณอาจใช้ png
stib

เป็นมูลค่าเพิ่มที่-q:v 1เป็นตัวเลือกที่มีประโยชน์มากที่นี่ในsuperuser.com/questions/318845/ …
Nikolay Shmyrev

27
mplayer -vo jpeg -sstep 5 file.avi

จะบันทึกเฟรมเป็นไฟล์ jpeg ทุก 5 วินาที

อย่างไรก็ตามมันจะไม่หยุดในตอนท้ายของไฟล์มันจะยังคงผลิตสำเนาของเฟรมสุดท้าย หากต้องการหลีกเลี่ยงปัญหานี้ให้ค้นหาระยะเวลาของวิดีโอในไม่กี่วินาทีโดยใช้เครื่องเล่นอื่นหรือกับ mplayer:

mplayer -vo null -ao null -frames 0 -identify file.avi

และค้นหาบรรทัดเช่น "ID_LENGTH = 147.00"

ลบ 2 จากความยาวและใช้ค่านี้สำหรับ-endposตัวเลือก ตัวอย่างเช่นสำหรับวิดีโอ 147 วินาที:

mplayer -vo jpeg -sstep 5 -endpos 145 file.avi

ฟังดูเหมือนบั๊ก mplayer วิธีแก้ปัญหาที่ดี
ต้มตุ๋น quixote

อย่างน้อยคุณสามารถพูดถึงระบบปฏิบัติการที่คุณใช้คำสั่งนี้ได้หรือไม่?
Tomáš Zato

เมื่อ 5 ปีก่อน แต่มันก็น่าจะเป็น Ubuntu Desktop รุ่นล่าสุดในเวลานั้น Ubuntu 10.4
เลียม

ฉันจะเลือกขั้นตอนที่สั้นกว่า 1 วินาทีได้อย่างไร มันยอมรับเฉพาะจำนวนเต็ม
fcpenha

ปัจจุบันใช้mpv --vo=image --sstep=5 movie.mkvงานได้ดีโดยไม่มีข้อผิดพลาดดังกล่าว ( mpvเป็นทางแยกของ mplayer) โดยใช้ mpv 0.27.0 บนเดเบียน
Adam Katz

11

ด้วยffmpegคุณสามารถทำสิ่งต่อไปนี้:

ffmpeg -ss 4 -i input.avi -s 320x240 -frames:v 1 output.jpg

คำสั่งนี้สร้างภาพขนาดย่อ JPG ขนาด 320 × 240 ในวินาทีที่ 4 ของวิดีโอ ใส่ไว้ในสคริปต์ที่เปลี่ยนเวลาและชื่อไฟล์และคุณเสร็จแล้ว

ข้อมูลเพิ่มเติม: สร้างภาพขนาดย่อทุก ๆ X วินาทีของวิดีโอ


ดูเหมือนว่าจะทำสิ่งที่ฉันต้องการ แต่มีปัญหาเดียว มันจะประมวลผลไฟล์ตั้งแต่เริ่มต้นในการวนซ้ำแต่ละครั้งทำให้ช้าลงอย่างมาก
เลียม

@Liam - มันช่วยได้ไหมถ้าคุณปล่อยเวลาออฟเซ็ตไว้ตามลำพัง (ตั้งไว้ที่ 1) และใช้-ss positionแฟล็กเพื่อค้นหาไฟล์เพิ่มเติมแทนหรือไม่ -ss Seek to given time position in seconds. hh:mm:ss[.xxx] syntax is also supported
Nifle

1
@liam: ใส่-ssก่อนหน้า-iเพื่อให้การค้นหาเกิดขึ้นก่อนที่วิดีโออินพุตจะถูกถอดรหัส สิ่งนี้ควรเร่งความเร็ว แหล่งที่มา
ต้มตุ๋น Quixote

2
มีวิธีที่ดีกว่าและเร็วกว่ามากในการทำกับ ffmpeg ดูคำตอบของฉันด้านล่าง
stib

โซลูชันของ stib คือ IMO ที่ดีที่สุด
กริฟ

8

หากคุณหลังจากชนิดของแผ่นติดต่อและถ้าคุณกำลังทำงานร่วมกับระบบปฏิบัติการยูนิกซ์เหมือน OS คุณสามารถใช้สคริปต์ที่ซับซ้อนเรียกไปยังจุดที่แผ่นติดต่อวีดีโอ * NIXสั้น VCS

ในพื้นหลังก็ใช้ffmpeg(โดยค่าเริ่มต้น) หรือmplayerดังนั้นจึงสามารถจัดการรูปแบบวิดีโอจำนวนมาก มันทำให้กระบวนการถ่ายภาพนิ่งจากภาพยนตร์โดยอัตโนมัติและจัดทำภาพเหล่านี้เป็นภาพที่มีส่วนหัวและส่วนท้าย คุณสามารถเลือกเช่นจำนวนการบันทึกที่คุณต้องการหรือความแตกต่างของเวลาระหว่างพวกเขา

สำหรับช่วงเวลา 10 นาทีการร้องขอจะเป็นเช่นนั้น:

vcs -i 10m input.avi

ตรวจสอบรายการตัวเลือก commandline ทั้งหมดสำหรับการปรับแต่งอื่น ๆ

นี่คือตัวอย่างแผ่นข้อมูลติดต่อที่นำมาจากหน้าแรก :

ป้อนคำอธิบายรูปภาพที่นี่


7

ด้วย VLC 1.1.0 ขึ้นไปคุณสามารถใช้ฟิลเตอร์วิดีโอฉาก:

vlc C:\video\to\process.mp4 --rate=1 --video-filter=scene --vout=dummy --start-time=10 --stop-time=11 --scene-format=png --scene-ratio=24 --scene-prefix=snap --scene-path=C:\path\for\snapshots\ vlc://quit

ด้านบนบันทึก 1 จากทุก ๆ 24 เฟรม (--scene-ratio = 24) เริ่มต้นที่ 00:00:10 และสิ้นสุดที่ 00:00:11

เพิ่งทดสอบและยืนยันว่าใช้งานได้กับ VLC 2.0.3 ในการติดตั้ง Windows 8 ใหม่ (ฉันไม่มีปลั๊กอินวิดีโอหรือซอฟต์แวร์เพิ่มเติม)

เอกสารฉบับเต็ม: http://wiki.videolan.org/How_to_create_thumbnails


2

VirtualDubสามารถทำสิ่งนี้เพื่อคุณ

File-> Export->Image sequence

ป้อนคำอธิบายรูปภาพที่นี่


สิ่งนี้จะบันทึกทุกเฟรมเป็นภาพหรือไม่?
เลียม

ใช่ทุกเฟรม
Shevek

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

1

คุณสามารถลองสิ่งนี้ได้

จากบรรทัดคำสั่ง VLC ...

vlc "C: \ YOUR \ file \ path \ file.avi" -V image --image-out-prefix = capname --image-out-ratio = 60

file.avi เป็นวิดีโอที่คุณต้องการจับภาพ capname เป็นคำนำหน้าของรูปภาพที่บันทึกคุณอาจต้องการเล่นด้วยอัตราส่วน (60 หมายความว่าจับภาพ 1 จาก 60 ภาพ) คุณสามารถเพิ่มคำสั่งเพิ่มเติมได้เช่น - jpeg รูปแบบภาพออกจะบันทึกตัวพิมพ์ใหญ่ของคุณเป็น jpegs แทนที่จะเป็น pngs --snapshot-path ช่วยให้คุณเลือกตำแหน่งที่จะบันทึกตัวพิมพ์ใหญ่ของคุณ

แหล่งที่มาของข้างต้น


ฉันได้รับข้อความนี้: ไม่สามารถโหลดตัวเลือกบรรทัดคำสั่งตรวจสอบว่าถูกต้อง
เลียม

บน Ubuntu ฉันได้รับข้อความนี้: ตัวเลือกที่ไม่รู้จักหรือไม่มีอาร์กิวเมนต์ที่จำเป็น `--image-out-prefix = capname '
เลียม

1

คุณสามารถข้ามเฟรมได้ใน VirtualDub เพียงใช้ตัวเลือก "Decimate By" ซึ่งอยู่ที่เมนู -> เมนู Frame Rate ตัวอย่างเช่นหากคุณตั้งค่า "Decimate By 100" จากนั้นใช้ไฟล์ -> ส่งออก -> ลำดับภาพมันจะบันทึกเฉพาะทุกๆเฟรมที่ 100

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