เชื่อมต่อไฟล์วิดีโอแบบโต้ตอบ


9

วิธีการต่อเชื่อม (เข้าร่วม) ไฟล์วิดีโอ MP4 หลายไฟล์เป็นไฟล์เดียว

มีโปรแกรมมากมายที่ทำเช่นนี้สำหรับสองไฟล์จากบรรทัดคำสั่ง ตัวอย่างเช่น

  • ffmpeg
  • avconv
  • mp4box

แต่บ่อยครั้งที่เราต้องการวิธีแก้ปัญหาในการทำสิ่งนี้แบบโต้ตอบ


1
คุณสามารถอธิบายสิ่งที่คุณหมายถึงโดยการโต้ตอบ?
slm

@slm ฉันหมายถึงโปรแกรมที่ขอให้ผู้ใช้ป้อนไฟล์อินพุตทีละไฟล์จากนั้นสร้างไฟล์เอาต์พุต จากนั้นทำการเชื่อมต่อ
Slyx

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

@slm ฉันโพสต์สิ่งนี้เพราะมันเป็นเรื่องจำเป็นสำหรับผู้ใช้มัลติมีเดียอย่างฉัน ดังนั้นฉันหวังว่ามันจะช่วยคนอื่น แน่นอนว่าการปรับปรุงใด ๆ มีมากกว่ายินดีต้อนรับ!
Slyx

1
@gold ฉันใส่การแก้ไขในคิว ffmpegแน่นอนโดยไม่ตายหรือล้าสมัย: ความgitมุ่งมั่นที่ผ่านมาmasterคือเมื่อ15 นาทีที่แล้วและฉันใช้มันทุกวัน
Anko

คำตอบ:


8

ฉันไม่ได้ลองวิธีนี้เมื่อเร็ว ๆ นี้ แต่ไม่เห็นว่าทำไมมันยังไม่ทำงาน ฉันเชื่อว่าคุณสามารถcat .mp4รวมไฟล์เข้าด้วยกันหากคุณไม่ต้องการทำอะไรอื่นนอกจากเชื่อมต่อไฟล์เหล่านั้น

1. การใช้แมว

$ cat file1.mp4 file2.mp4 > file3.mp4
$ ffmpeg -i file3.mp4 -qscale:v 2 output.avi

ฉันยังคงใช้อยู่ffmpegตลอดเวลามันสามารถต่อไฟล์เข้าด้วยกันได้

2. การใช้ ffmpeg

  1. ทำรายการไฟล์เพื่อต่อกัน

    $ cat inputs.txt 
    file sample_mpeg4.mp4
    file sample_mpeg4.mp4
  2. concatenate

    $ ffmpeg -f concat -i inputs.txt -c copy out.mp4
    
    $ ll |grep -E "sample|out"
    -rw-rw-r--. 1 saml saml 491860 Feb 19 23:36 out.mp4
    -rw-r--r--. 1 saml saml 245779 Feb 19 23:32 sample_mpeg4.mp4

    วิธีการอื่น ๆ จะกล่าวถึงในไฟล์ FFmpeg wiki: วิธีการเชื่อมไฟล์มีเดีย (เชื่อมโยงรวม) เข้าด้วยกัน

    หมายเหตุ: Ubuntu ไม่รองรับconcatรูปแบบ คุณต้องใช้โปรโตคอล concat นอกจากนี้ยังมีตัวเลือก codec ต่อสตรีม ดังนั้นการใช้โปรโตคอล concat ผลลัพธ์ดังนี้:

    $ ffmpeg -i input1.mp4 -vcodec copy -acodec copy \
         -vbsf h264_mp4toannexb -f mpegts intermediate1.ts
    
    $ ffmpeg -i input2.mp4 -vcodec copy -acodec copy \
         -vbsf h264_mp4toannexb -f mpegts intermediate2.ts
    
    $ ffmpeg -i "concat:intermediate1.ts|intermediate2.ts" \
         -vcodec copy -acodec copy -absf aac_adtstoasc output.mp4

    ตัวเลือกอูบุนตู ffmpeg มีเอกสารที่นี่


น่าสนใจ! ฉันไม่รู้ว่าcatเพียงพอสำหรับไฟล์ MP4! การแก้ปัญหาไม่ได้เป็นแบบโต้ตอบ!
Slyx

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

2
ฉันยืนยันว่า การใช้catไม่ใช่โซลูชันที่ถูกต้อง ไฟล์ที่สร้างโดยการรวมcatสองไฟล์จะแสดงเนื้อหาของไฟล์อินพุตแรกเท่านั้น!
Slyx

@Slyx - cat ทำงาน แต่การประทับเวลาไม่ถูกต้องดังนั้นเมื่อคุณพยายามเล่นกลับเครื่องเล่นวิดีโอเริ่มสับสนจากการกระโดดในการประทับเวลาจาก 00 ถึงสิ้นสุดจากนั้นกลับเป็น 00 หากคุณต้องการแปลงรหัสวิดีโอนี้ จะได้รับการแก้ไขเป็นส่วนหนึ่งของกระบวนการนั้น มีวิธีในการสร้างการประทับเวลาด้วยเช่นกัน
slm

นั่นคือสิ่งที่ฉันหมายถึงเกินไป เนื้อหาทั้งสองอยู่ที่นั่น แต่เครื่องเล่นสื่อตรวจพบเนื้อหาแรกเท่านั้น
Slyx

4

ฉันใช้ MP4Box เป็นฐานการทำงาน
สคริปต์ที่ฉันแนะนำให้อ่านไฟล์ทั้งหมดทีละตัวตรวจสอบแต่ละไฟล์ (สภาพอากาศเป็นไฟล์ธรรมดา) ขอให้ผู้ใช้ใส่ชื่อไฟล์ที่จะสร้าง

#!/bin/bash
printf "###  Concatenate Media files ###\n"
fInputCount=0
# Reading input files
IFS=''
while (true)
do
    let currentNumber=$fInputCount+1 
    printf "File n°%s (\"ok\" to finish): " $currentNumber
    read inputFile
    [ "$inputFile" == "ok" ] && break
    [ ! -e "$inputFile" ] || [ ! -f "$inputFile" ] && printf "\"%s\" : Invalid filename. Skipped !\n" "$inputFile" && continue
    ((fInputCount++))
    inputFileList[$fInputCount]=$inputFile
    printf "\"%s\" : Added to queue !\n" "$inputFile"
done
[ "$fInputCount" == "0" ] || [ "$fInputCount" == "1" ] && echo "No enough input data. BYE ! " && exit
# Listing the input file list 
for ((i=1;i<=$fInputCount;i++))
do
    printf "%2d : %s\n" $i ${inputFileList[$i]}
done
# Reading the output filename
while (true)
do
    printf "Output file without extention (\"none\" to dismiss) : "
    read outputRead
    [ "$outputRead" == "none" ] && echo "Dismissed. BYE ! " && exit
    [ "$outputRead" == "" ] && echo "Try again ! " && continue
    [ -e "$outputRead" ] && echo "\"$outputRead\" exists. Try again !" && continue
    outputFile=$outputRead.mp4
    echo "Output to \"$outputFile\". Go !" && break
done
# Creating a random temporary filename
tmpOutFile="/tmp/concatMedia"`date +"%s%N"| sha1sum | awk '{print $1}'`".mp4"
# Joining the two first input files
MP4Box -cat "${inputFileList[1]}" -cat "${inputFileList[2]}" $tmpOutFile
# Adding all other files
for ((i=3;i<=$fInputCount;i++))
do
    tmpIntermediateFile=$tmpOutFile
    tmpOutFile="/tmp/concatMedia"`date +"%s%N"| sha1sum | awk '{print $1}'`".mp4"
    MP4Box -cat $tmpIntermediateFile -cat "${inputFileList[$i]}" $tmpOutFile
    rm $tmpIntermediateFile
done
mv $tmpOutFile "$outputFile"
# Finished
echo "\"$outputFile\" Saved !"
โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.