วางเฟรมคู่หรือคี่ทุกเฟรมโดยใช้ FFmpeg?


14

มีวิธีที่ถูกต้องในการใช้วิดีโอดิบและแยกออกจากวิดีโอใหม่ที่มีเฉพาะเฟรมแปลก ๆ หรือแม้กระทั่งเฟรม (ตามตัวเลือก) หรือไม่

ตัวอย่างเช่น:

ฉันมี "blah.yuv" กับ 400 เฟรม (0-399) ฉันต้องการสร้าง "blahOdd.yuv" ที่มีเฟรม 1-399 (1,3,5,7 ... 399) และ "blahEven" ที่มีเฟรม 0-398 (0,2,4,6 ... 398 )

ความคิดใด ๆ วิธีการใช้ FFmpeg เท่านั้น?

คำตอบ:


11

หากต้องการทำงานอย่างถูกต้องอันดับแรกให้แปลงวิดีโอเป็นบิตสตรีม RAW YUV (หากยังไม่พร้อม) โดย:

ffmpeg -i input.mp4 -an -vcodec rawvideo -pix_fmt yuv420p rawbitstream.yuv

ขั้นตอนถัดไป: selectตัวกรองใช้นิพจน์ซึ่งnเป็นหมายเลขเฟรม

ffmpeg -r 2 -s WxH -i rawbitstream.yuv -filter:v select="mod(n-1\,2)" \
-c:v rawvideo -r 1 -format rawvideo -pix_fmt yuv420p -an odd.yuv

ffmpeg -r 2 -s WxH -i rawbitstream.yuv -filter:v select="not(mod(n-1\,2))" \
-c:v rawvideo -r 1 -format rawvideo -pix_fmt yuv420p -an even.yuv

ในการffmpegไม่มีเฟรมที่ซ้ำกันคุณต้องบังคับครึ่งหนึ่งของอัตราเฟรมของอินพุตของคุณดังนั้นคุณจึงตั้งค่า "2" เป็นอินพุตและ "1" เป็นเอาต์พุต อย่าลืมแทนที่ WxH ด้วยขนาดจริงของคลิปของคุณเนื่องจากบิตสตรีมแบบดิบไม่มีส่วนหัวที่นำข้อมูลนี้ไปใช้

แทนที่จะเป็นข้างต้นความเป็นไปได้อีกอย่างก็คือการเพิ่มsetptsตัวกรองเพื่อตั้งค่าการประทับเวลาใหม่สำหรับเอาต์พุต แต่ระวังเพราะมันลดลงเฟรมไม่ถูกต้อง ที่นี่ 25 คืออัตราเฟรมเอาต์พุตจริงที่คุณต้องการ:

ffmpeg -i input.mp4 -filter:v select="mod(n-1\,2)",setpts="N/(25*TB)" \
-c:v rawvideo -r 12.5 -format rawvideo -pix_fmt yuv420p -an odd.yuv

ffmpeg -i input.mp4 -filter:v select="not(mod(n-1\,2))",setpts="N/(25*TB)" \
-c:v rawvideo -r 12.5 -format rawvideo -pix_fmt yuv420p -an even.yuv

แน่นอนว่าคุณสามารถเลือกรูปแบบพิกเซลอื่น (อย่างใดอย่างหนึ่งffmpeg -pix_fmts) ตรวจสอบให้แน่ใจว่าเมื่ออ่านไฟล์คุณรู้ขนาดพิกเซลและรูปแบบพิกเซล:

ffmpeg -f rawvideo -s:v 1280x720 -pix_fmt yuv420p input.yuv …

ขอบคุณสำหรับ FFMPEG เวอร์ชันใหม่ควรเป็น -vf แทนที่จะเป็น -filter: v นอกจากนี้ควรเป็น mod (n-1 \, 2) เนื่องจากการนับ n ดูเหมือนจะเริ่มจาก 1 ขณะที่เฟรมนับจาก 0 (มิฉะนั้นเฟรมแรกจะทำซ้ำ 3 ครั้ง) แต่ยังคงมีปัญหามันทำซ้ำเฟรมในขณะที่ฉันต้องการกำจัดพวกเขา - เช่นคลิปสุดท้ายจะมีเพียงครึ่งหนึ่งของเฟรม
Mark

-vf-filter:vเป็นนามแฝงของ ตอนนี้ฉันไม่สามารถทดสอบได้อย่างน่าเชื่อถือ แต่จะตรวจสอบในภายหลังเมื่อฉันกลับไปที่เครื่องของฉัน บางทีtinterlaceตัวกรองสามารถทำเช่นเดียวกันได้หรือไม่
slhck

ฉันได้ลอง '-r 2 -i blah.yuv -r 1' แต่มันแสดงให้ฉันเห็นว่ามีข้อผิดพลาดตัวเลือก framerate ไม่พบ
Mark

อืม .. ขอโทษด้วย, คร่ำครวญว่าสิ่งนี้ใช้ไม่ได้ (อีกต่อไป?) และสำหรับภาพเท่านั้น
slhck

1
@AnmolSinghJaggi ไม่มันแค่วางเฟรม แต่ฉันไม่แน่ใจว่ามันจะถูกกำหนดไว้อย่างไร (เช่นวางทุกเฟรมที่คี่) มันจะขึ้นอยู่กับรหัสเวลาซึ่งอาจไม่ถูกต้อง
slhck

2

หาก ffmpeg ของคุณถูกสร้างด้วยธง AviSynth ฉันเชื่อว่าคุณสามารถส่ง.avsไฟล์ได้

คุณสามารถตรวจสอบได้โดยการเรียกใช้ffmpegและค้นหา--enable-avisynthในข้อมูล การกำหนดค่า--enable-AviSynth

ffmpeg -i blahEven.avs blahEven.yuvถ้ามันมีคุณสามารถใช้มันเพื่อต้องการ:

อยู่ที่ไหนblahEven.avs:

ffvideosource ( "blah.yuv"). SelectEven ()

SelectOdd()สำหรับเฟรมแปลกการใช้งาน

สำหรับการใช้งานที่ได้รับคำแนะนำเพิ่มเติมโปรดดูเอกสารSelectEvery


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

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