ทำซ้ำ / วนวิดีโออินพุตด้วย ffmpeg หรือไม่


52

ฉันต้องการวนวิดีโอ mp4 ด้วย ffmpeg และรักษาการตั้งค่าปัจจุบันและตัวแปลงสัญญาณ

ตัวอย่างเช่นถ้า input.mp4 ยาว 0:10 และฉันต้องการวนรอบ 4 ครั้งดังนั้น output.mp4 ยาว 0:40 ฉันจะเปลี่ยนบรรทัดคำสั่งต่อไปนี้ได้อย่างไร

ffmpeg -i input.mp4 -c copy output.mp4

ฉันเหนื่อย...

ffmpeg -loop 4 -i input.mp4 -c copy output.mp4

... แต่ฉันได้รับข้อผิดพลาด "ไม่พบลูปตัวเลือก"


ใช้ Quicktime 7 pro และ mov container ดังนั้นคุณจะไม่ได้ขนาดไฟล์ใหญ่กว่าขนาดโอเพนซอร์ส
ДмитрийМышков

คำตอบ:


69

Concat demuxer

สิ่งนี้ช่วยให้คุณวนซ้ำอินพุตโดยไม่ต้องเข้ารหัสอีกครั้ง

  1. ทำไฟล์ข้อความ เนื้อหาของไฟล์ข้อความตัวอย่างเพื่อทำซ้ำ 4 ครั้ง

    file 'input.mp4'
    file 'input.mp4'
    file 'input.mp4'
    file 'input.mp4'
    
  2. จากนั้นเรียกใช้ffmpeg:

    ffmpeg -f concat -i list.txt -c copy output.mp4
    

สำหรับผู้ใช้ Linux

ตัวอย่างนี้เหมือนกับด้านบน แต่คุณไม่จำเป็นต้องทำด้วยตนเองlist.txt:

for i in {1..4}; do printf "file '%s'\n" input.mp4 >> list.txt; done
ffmpeg -f concat -i list.txt -c copy output.mp4

ด้วยเชลล์ทันสมัยที่ใช้กันมากที่สุดคุณสามารถหลีกเลี่ยงการสร้างlist.txtไฟล์ได้ทั้งหมด ตัวอย่างเช่นด้วย bash:

ffmpeg -f concat -i <(for i in {1..4}; do printf "file '%s'\n" input.mp4; done) -c copy output.mp4

ดูเพิ่มเติมที่:


ตัวกรองลูป

ตัวอย่างการใช้ตัวกรองลูปเพื่อวน 4 ครั้งแต่ละลูปคือ 75 เฟรมแต่ละลูปจะข้าม 25 เฟรมแรกของอินพุต:

ffmpeg -i input -filter_complex loop=loop=3:size=75:start=25 output
  • หรือใช้ชวเลข: loop=3:75:25
  • การกรองต้องมีการเข้ารหัสใหม่
  • ตัวกรองนี้จะวางเฟรมทั้งหมดในหน่วยความจำ
  • การใช้loop=3จะวนซ้ำ 4 ครั้ง
  • -1ห่วงการใช้งานเพียบ
  • คุณต้องแสดงรายการจำนวนเฟรมที่จะวนซ้ำ (แสดงเป็น 75 ในตัวอย่างด้านบน) ค่าสูงสุดคือ 32767
  • ffmpeg -h filter=loopยังเห็น

ตัวกรองภาพยนตร์

กรองภาพยนตร์มีตัวเลือกในการวนรอบ ดูคำตอบด้านล่างโดย Monah Tuk การกรองต้องมีการเข้ารหัสใหม่ สำหรับเสียงใช้ตัวกรอง amovie


-stream_loop ตัวเลือก

ดูคำตอบด้านล่างโดย Thingy และตอบโดย Gyan

โปรดทราบว่าตัวเลือกนี้เป็น buggy (ดูรายงานข้อผิดพลาด# 5719 , # 6121และ# 7043 ) ดังนั้นอาจไม่สามารถใช้งานได้กับบิลด์เก่า (ทุกอย่างที่เก่ากว่า 2018 06-27 รวมถึงสาขาวางจำหน่าย FFmpeg 4.0.x) สำหรับผู้ใช้งานบิลด์เก่าตามที่ mulvya พูดถึงในตั๋ว # 6121 วิธีแก้ปัญหาหนึ่งคือการรีมูฟ mux ใหม่เป็น MKV หรือ TS ก่อนจากนั้นใช้-stream_loopในคำสั่งถัดไป


-loop ตัวเลือก

-loopตัวเลือกที่เป็นเฉพาะกับdemuxer ไฟล์ภาพและGIF Muxerดังนั้นจึงไม่สามารถนำมาใช้สำหรับไฟล์วิดีโอทั่วไป แต่ก็สามารถนำมาใช้ในวงอนันต์ชุดของภาพใส่ ตัวอย่างนี้จะวนซ้ำไปเรื่อย ๆ แต่-t 30จะ จำกัด ระยะเวลาเอาต์พุตเป็น 30 วินาที:

ffmpeg -loop 1 -i %03d.png -t 30 output.mkv

หรือเพื่อวนลูปเอาต์พุต GIF:

ffmpeg -i input -loop 3 output.gif

มันใช้งานได้ดีกับไฟล์ mp4 หรือไม่?
โธมัสคิง

3
ฉันได้รับข้อผิดพลาดนี้> <(for i in {1..4}; do printf "file '%s'\n" input.mp4; done) -bash: /dev/fd/63: Permission denied
JZ11

1
@jamesfzhang - ฉันคิดว่าเป็นเพราะคุณต้องการเส้นทางที่แน่นอนไปยังไฟล์ (ดังอธิบายไว้ที่นี่: trac.ffmpeg.org/wiki/Concatenate ) คุณสามารถเขียน: ffmpeg -safe 0 -f concat -i <(สำหรับ i ใน {1..4}; ให้พิมพ์ "file '$ PWD' / '% s' \ n" input.mp4; ) -c คัดลอก output.mp4
Plenus Franckly

1
สำหรับฉันงานนี้จะทำซ้ำเต็มเวลาวิดีโอโดยไม่ต้อง fames ข้าม 4 ครั้งffmpeg -i video.mp4 -filter_complex "loop=4:32767" output.mp4
Vlad

ปัญหานี้มีอายุ 4 ปีและไม่มีใครสังเกตเห็นว่าการเชื่อมโยงไปยังปัญหาที่สองใน-stream_loopส่วนจะชี้ไปที่ตั๋วเดียวกับคนแรก ...
Leonid Usov

15

อย่างน้อยใน FFmpeg 2.8.x (แต่ oldie ควรทำงานด้วย) คุณสามารถใช้lavfiเป็นรูปแบบอินพุตและกราฟตัวกรองที่ซับซ้อนโดยใช้movieและsetptsตัวกรองเป็นอาร์กิวเมนต์สำหรับ-iตัวเลือก

คำสั่งถัดไปทำงานให้คุณ:

ffmpeg -re -f lavfi -i "movie=filename=input.mp4:loop=0, setpts=N/(FRAME_RATE*TB)" output.mp4

loop=อาร์กิวเมนต์Zero หมายถึงวงอินฟินิตี้ ค่าที่มากกว่าศูนย์ชุดการนับซ้ำจะทำซ้ำ setptsฟิลเตอร์ที่จำเป็นสำหรับการปรับ PTS สำหรับการทำซ้ำครั้งที่สองและต่อมามิฉะนั้น muxers ส่วนใหญ่จะล้มเหลวเมื่อ PTS ที่ไม่ใช่แบบโมโนโพนิกเพิ่มขึ้น: ลูปไม่คำนวณซ้ำ PTS

โปรดทราบว่าการใช้ตัวกรองสมมติว่าบายพาสเฟรมโดยไม่ต้องถอดรหัส / เข้ารหัสเป็นไปไม่ได้: โดยตัวกรองการออกแบบเกี่ยวข้องกับเฟรมถอดรหัสเท่านั้น

ที่ FFmpeg 2.8.2 ตัวเลือกการป้อนข้อมูลใหม่ที่นำ-stream_loopมาใช้ ฉันแรกดูมันทำงานง่ายขึ้นและอนุญาตให้คัดลอกเนื้อหาโดยไม่ต้องแปลงรหัส:

ffmpeg -re -stream_loop -1 -i input.mp4 -c copy -y output.mp4

แต่จะไม่คำนวณ PTS อีกครั้งและไฟล์เอาต์พุตไม่ถูกต้อง หากคุณเพิ่มตัวกรองเพื่อแก้ไข PTS (ดูsetpts) คุณต้องลบ-c copyด้วย ตัวกรองบิตสตรีมเท่านั้นที่สามารถจัดการกับแพ็คเก็ตที่เข้ารหัสได้ แต่ไม่มีตัวกรองบิตสตรีมใด ๆ ที่จะแก้ไข PTS (ดู: https://ffmpeg.org/ffmpeg-bitstream-filters.html )

ในกรณีใด ๆ ffmpeg ในการส่งครั้งที่สองล้มเหลวโดยมีข้อผิดพลาด:

input.mp4: Resource temporarily unavailable

เป็นที่รู้จักสำหรับฉัน : ใช้คอนเทนเนอร์สำหรับไฟล์อินพุตโดยไม่มีข้อ จำกัด PTS (สตรีมคอนเทนเนอร์) หนึ่งในนั้นรู้จักฉันคือ MPEG-TS ดังนั้นคุณสามารถแปลงไฟล์ MP4 เป็น MPEG-TS ได้ง่ายๆ:

ffmpeg -i input.mp4 -c copy -bsf:v h264_mp4toannexb -f mpegts input.ts

และใช้คำสั่งถัดไปเพื่อเขียนไฟล์อินฟินิตี้:

ffmpeg -re -stream_loop -1 -i input.ts -c copy -strict -2 -bsf:a aac_adtstoasc -y output.mp4

(ควรใช้ตัวกรองบิตสตรีมหากจำเป็นต้องใช้กับตัวอย่างของฉัน)

FFmpeg> = 2.8.2 เป็นสิ่งจำเป็นในกรณีนี้


1
การเรียกใช้คำสั่งนั้นทำให้ฉันเกิดข้อผิดพลาด: "[mp4 @ 00000000053fa1a0] ไม่พบแท็กสำหรับ codec rawvideo ในสตรีม # 0 ตัวแปลงสัญญาณที่ไม่รองรับในคอนเทนเนอร์" หากฉันเพิ่ม -vcodec h264 ก่อนอินพุตข้อผิดพลาดนั้นจะหายไป แต่ตัวเข้ารหัสไม่ออก การจัดหาจำนวนลูปที่ไม่เป็นศูนย์จะทำให้เกิดข้อผิดพลาดได้มาก แต่จะออกจากการทำงาน ไฟล์ไม่ใช่เอาต์พุตที่ถูกต้อง
Gyan

1
เอกสารสำหรับ stream_loop บอกว่า "Loop 0 หมายถึงไม่มีการวนซ้ำวนซ้ำ -1 หมายถึงการวนซ้ำไม่สิ้นสุด"
Gyan

ดูเหมือนว่าไฟล์อินพุตที่ไม่ถูกต้อง คุณสามารถแบ่งปันได้ไหม "Loop 0 หมายถึงไม่มีการวนซ้ำวน -1 หมายถึงการวนซ้ำไม่สิ้นสุด" - ดูเหมือนว่าฉันเห็นเอกสารเก่า :-)
Monah Tuk

1
ฉันลืม: ตัวกรองที่สมมติว่าแปลงรหัส (ถอดรหัส / เข้ารหัส) โดยการออกแบบ. -c copyดังนั้นคุณต้องเอา แก้ไขคำตอบแล้ว
Monah Tuk

1
ยินดีที่ได้ทราบ แต่นั่นเป็นข้อ จำกัด ที่สำคัญหากคุณมีการวนซ้ำขนาดใหญ่เพื่อสร้าง
Gyan

14

ด้วย ffmpeg 2.8.4 คำสั่งต่อไปนี้จะสร้าง output.mp4 ที่เป็นสำเนาซ้ำของ input.mp4 จนกว่ากระบวนการ ffmpeg จะหยุดลง:

ffmpeg -stream_loop -1 -i input.mp4 -c copy output.mp4

คำสั่งนี้จะไม่ยุติด้วยตัวเองและไฟล์ที่ส่งออกจะเติบโตอย่างไม่ จำกัด


2
ดูเหมือนว่าจะเป็นวิธีที่เร็วที่สุด
josef

2
วิธีที่เร็วที่สุดคือการบอกวิธีการนี้จะเพิ่มวิดีโอได้นานหลายชั่วโมงในเวลาไม่กี่วินาที
SleighBoy

นี่เป็นวิธีที่สะดวกสบายมากเนื่องจากไม่จำเป็นต้องสร้างไฟล์ที่มีบรรทัดการทำซ้ำ
Markus Zeller

-1

ถาม: "... ฉันจะเปลี่ยนบรรทัดคำสั่งต่อไปนี้ได้อย่างไร? ffmpeg -i input.mp4 -c copy output.mp4"

ตอบ: วิธีการง่ายๆที่หลีกเลี่ยงปัญหาที่คำสั่งทำงานร่วมกับเวอร์ชันใดคือ 'วิธีแก้ปัญหาเล็กน้อย':

ffmpeg -i input.mp4 -i input.mp4 -i input.mp4 -i input.mp4 -c copy output.mp4

ดูเพิ่มเติมที่: https://trac.ffmpeg.org/wiki/Concatenateสำหรับตัวอย่างมากมาย


2
นี้ไม่ได้ทำใด ๆ ที่เรียงต่อกัน ต้องใช้วิธี concat อย่างน้อยหนึ่งวิธี: โปรโตคอลตัวกรองหรือตัวกรอง demuxer ในคำสั่งนี้การจับคู่อัตโนมัติของ ffmpeg จะเลือกหนึ่งวิดีโอเสียงหนึ่งเสียงและสตรีมคำบรรยายหนึ่งบทจากอินพุต มันเหมือนกันกับคำสั่งแรกของ OP
Gyan

ขอบคุณสำหรับการทดสอบที่ Mulvya เนื่องจากแตกต่างจากพฤติกรรมที่อธิบายไว้ในเอกสาร: ffmpeg.org/ffmpeg.html#Description - หากมีความคล้ายคลึงกันในชื่อไฟล์โดยใช้ "-i -i /tmp/test%d.mp4" ( et. al) ก็เป็นไปได้เช่นกัน
Rob
โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.