FFmpeg แบ่งวิดีโอและรวมกลับ


8

ฉันพยายามใช้ FFmpeg เพื่อแยกวิดีโอตามบางส่วนstart_timeและend_timeอินพุตและแทนที่วิดีโอเหล่านั้นด้วยไฟล์วิดีโออื่น ๆ ตัวอย่างเช่นสำหรับอินพุต10 15ฉันจะต้องแทนที่ EXACT วินาที10 to 15ด้วยวิดีโออื่น

ตกลง. สิ่งที่อยู่ในใจของฉันคือ:

  1. ก่อนแบ่งวิดีโอ (ในกรณีนี้ 0-10, 10-15 และ 15-end)
  2. แทนที่ 10-15 ด้วยวิดีโออื่น
  3. รวมวิดีโอย่อยทั้งหมดกลับเข้าที่

คำถามแรก: นี่เป็นทางออกที่ดีที่สุดและเร็วที่สุดหรือไม่? เรามีคำสั่งที่ง่ายกว่าหรือเครื่องมืออื่น ๆ เพื่อแทนที่ช่วงเวลาเฉพาะในวิดีโอด้วยวิดีโออื่นหรือไม่?

คำถามที่สอง: สมมติว่า FFmpeg เป็นทางออกที่ทำงานได้เมื่อฉันเพียงแค่ใช้คำสั่งffmpeg -I input.video -ss 10 -t 5 -c copy output.mp4รหัสการประมวลผลวิดีโอของฉันไม่สามารถอ่านและประมวลผลไฟล์ ฉันใช้mediainfoเครื่องมือเพื่อเปรียบเทียบไฟล์สองไฟล์และสังเกตเห็นความแตกต่างของขนาดส่วนหัวในขณะที่ตัวแปลงสัญญาณวิดีโอทั้งหมดเกี่ยวข้องกัน ฉันสังเกตเห็นว่าขนาด HEADER มีความแตกต่างซึ่งเห็นได้ชัดว่าทำให้เกิดปัญหา มีวิธีใดที่จะบังคับขนาดส่วนหัวด้วย (นอกเหนือจากตัวแปลงสัญญาณ) เหมือนกันหรือไม่

ปรับปรุง: นี่คือ.mp4ไฟล์ต้นฉบับที่ทำงานได้ดีในโปรแกรมจำลอง


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

@slhck รหัสการประมวลผลวิดีโอเป็นฐานรหัสขนาดใหญ่ ฉันไม่สามารถแบ่งปันได้ ด้วยเหตุผลบางประการไฟล์ต้นฉบับจะถูกอ่าน แต่ไม่ใช่ไฟล์ที่สร้างขึ้นใหม่ อย่างไรก็ตามฉันสามารถแชร์.mp4ไฟล์ต้นฉบับได้ถ้าต้องการ
Ariana

ฉันใช้เครื่องมือ mediainfo เพื่อเปรียบเทียบไฟล์ทั้งสองและสังเกตเห็นความแตกต่างของขนาดส่วนหัวและสิ่งของ
Ariana

มีต้นฉบับจะช่วย แต่เราจะไม่สามารถแก้ไขปัญหาได้ว่าทำไมมันไม่สามารถอ่านได้ฉันกลัวว่าถ้าเป็นรหัสภายใน
slhck

@slhck ฉันอัปโหลดไฟล์ อัปเดตคำถามของฉันแล้ว
Ariana

คำตอบ:


9

การใช้trimและconcat- ไฟล์ต้นฉบับที่มีตัวแปลงสัญญาณที่แตกต่างกัน

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

คุณสามารถทำทุกอย่างได้ในครั้งเดียวโดยไม่ต้องแยกไฟล์โดยใช้ตัวกรองtrimและconcat:

ffmpeg -i edv_g24.mp4 -i short-video.mp4 -filter_complex "\
[0:v]trim=0:10,setpts=PTS-STARTPTS[v0]; \
[1:v]trim=0:5,setpts=PTS-STARTPTS[v1]; \
[0:v]trim=15:30,setpts=PTS-STARTPTS[v2]; \
[v0][v1][v2]concat=n=3:v=1:a=0[out]" \
-map "[out]" output.mp4

ที่นี่trimใช้เพื่อระบุแต่ละส่วนของสตรีมวิดีโออินพุต ( 0:v, 1:v) ที่คุณต้องการเชื่อมต่อในภายหลัง ชิ้นส่วนเหล่านี้มีชื่อผ่านv0 v2( setptsตัวกรองรีเซ็ตการประทับเวลาของแต่ละส่วนเหล่านี้เป็น 0 ซึ่งจำเป็นสำหรับการต่อข้อมูล) ต่อมาเราต่อสามส่วนเข้าด้วยกัน

หากคุณต้องการตัดแต่งจากการประทับเวลาที่แน่นอนไปยังจุดสิ้นสุดให้ใช้trim=start=15แทนการระบุช่วง

หากไฟล์ของคุณมีเสียงคุณจะต้องตัดสตรีมเหล่านั้นแยกต่างหาก:

ffmpeg -i edv_g24_2.mp4 -i short-video.mp4 -filter_complex "\
[0:v]trim=0:10,setpts=PTS-STARTPTS[v0]; \
[0:a]atrim=0:10,asetpts=PTS-STARTPTS[a0]; \
[1:v]trim=0:5,setpts=PTS-STARTPTS[v1]; \
[1:a]atrim=0:5,asetpts=PTS-STARTPTS[v1]; \
[0:v]trim=15:30,setpts=PTS-STARTPTS[v2]; \
[0:a]atrim=15:30,asetpts=PTS-STARTPTS[a2]; \
[v0][a0][v1][a1][v2][a2]concat=n=3:v=1:a=1[outv][outa]" \
-map "[outv]" -map "[outa]" output.mp4

โปรดทราบว่าวิดีโอและเสียงจะได้รับการเข้ารหัสอีกครั้งในกรณีนี้ - ตรวจสอบให้แน่ใจว่าได้ระบุเป้าหมายคุณภาพผลลัพธ์ที่เหมาะสม (เช่น-crfสำหรับ x264, x265 หรือ libvpx-vp9) คุณสามารถอ่านเพิ่มเติมเกี่ยวกับเรื่องนี้ในวิกิพีเดีย FFmpeg เช่นการVP9หรือH.264

ใช้ส่วนบุคคล

หากคุณต้องการแยกคลิปและประกอบใหม่ในภายหลัง:

ffmpeg -i edv_g24.mp4 -ss 0 -to 10 -c copy part1.mp4
ffmpeg -i edv_g24.mp4 -ss 10 -to 15 -c copy part2.mp4
ffmpeg -i edv_g24.mp4 -ss 15 -c copy part3.mp4

ffmpeg -i part1.mp4 -i short-video.mp4 -i part3.mp4 -filter_complex \
"[0:v][1:v][2:v]concat=n=3:v=1:a=0[outv]" \
-map "[outv]" -t 30 output.mp4

หากไฟล์มีเสียงให้ใช้แนวทางเดียวกันกับด้านบน:

ffmpeg -i part1.mp4 -i short-video.mp4 -i part3.mp4 -filter_complex \
"[0:v][0:a][1:v][1:a][2:v][2:a]concat=n=3:v=1:a=1[outv][outa]" \
-map "[outv]" -map "[outa]" -t 30 output.mp4

นี่จะเข้ารหัสวิดีโอสตรีมอีกครั้ง มันตรงไปตรงมามากกว่าเล็กน้อย แต่ก็ควรจะเทียบเท่ากับวิธีการข้างต้น

ใช้concatdemuxer

ในหลักการคุณสามารถลองเชื่อม bitstreams โดยไม่ต้องเข้ารหัสมันใหม่โดยใช้ concat demuxer สร้างไฟล์ชื่อconcat.txtและเพิ่มรายการต่อไปนี้ (ตรงกับวิดีโอคลิปที่สร้างขึ้นด้านบน):

file 'part1.mp4'
file 'short-video.mp4'
file 'part3.mp4'

จากนั้นเชื่อมไฟล์แต่ละไฟล์เหล่านี้:

ffmpeg -f concat -i concat.txt -c copy output.avi

อย่างไรก็ตามสิ่งนี้ต้องการคลิปของคุณที่มีโคเดก, ความละเอียด, framerate และอื่น ๆ ที่เหมือนกัน - ดังนั้นมันจึงไม่สามารถทำงานได้กับแหล่งกำเนิดที่หลากหลายทุกชนิด

ใช้concatโปรโตคอล

การต่อข้อมูลระดับไฟล์แบบข้างต้นสามารถทำได้โดยใช้concatโปรโตคอลเช่นกันโดยมีข้อ จำกัด แบบเดียวกับข้างบน (โคเดกตัวเดียวกันความละเอียด ฯลฯ ):

ffmpeg -i "concat:part1.avi|part2.avi|part3.avi" -c copy output.mp4

สำหรับข้อมูลเพิ่มเติมเกี่ยวกับการต่อข้อมูลให้อ่านหน้าFFmpeg Wiki ที่เกี่ยวข้อง


ดูสมบูรณ์มาก! ขอบคุณ ฉันจะลองพวกเขา!
Ariana

Idk ทำไมใช้concatวิธีการโยนข้อผิดพลาด:[concat @ 00000000025c2560] Line 1: unknown keyword 'part1.mp4 \\ text.txt: Invalid data found when processing input
Ariana

สำหรับ "การใช้แต่ละเซกเมนต์" ฉันเห็นหยุดและตัดเอาท์พุทออกเล็กน้อย มีวิธีแก้ไขปัญหานี้หรือไม่?
Ariana

วิธีที่ 1 ทำงานได้อย่างสมบูรณ์ สิ่งหนึ่ง: เราจะระบุ "จนจบ" ได้อย่างไรโดยไม่ระบุหมายเลขเฉพาะ (แทน 30 วินาที)
Ariana

1
ขออภัยทำผิดพลาด สำหรับconcatdemuxer ไวยากรณ์ต่างกัน แก้ไขแล้ว หากต้องการไปให้ถึงจุดสิ้นสุดให้trim=start=15ดูเอกสารประกอบของตัวกรองการตัดแต่ง: ffmpeg.org/ffmpeg-filters.html#trim - สำหรับปัญหาเกี่ยวกับเวลาสิ่งนี้ขึ้นอยู่กับแหล่งข้อมูลของคุณ ยังไม่มีปัญหาในการต่อเชื่อมกับคลิปที่คุณอัปโหลด
slhck
โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.