FFmpeg: วิธีแบ่งวิดีโออย่างมีประสิทธิภาพ?


103

ฉันต้องการแบ่งวิดีโอ avi ขนาดใหญ่ออกเป็นวิดีโอขนาดเล็กสองรายการต่อเนื่องกัน ฉันใช้ ffmpeg

วิธีหนึ่งคือเรียกใช้ ffmpeg สองครั้ง:

ffmpeg -i input.avi -vcodec copy -acodec copy -ss 00:00:00 -t 00:30:00 output1.avi
ffmpeg -i input.avi -vcodec copy -acodec copy -ss 00:30:00 -t 00:30:00 output2.avi

แต่ตาม manpage ของ ffmpeg ผมสามารถทำให้มากกว่าหนึ่ง ouput ไฟล์จากแฟ้มใส่หนึ่งโดยใช้เพียงหนึ่งบรรทัด:

ffmpeg -i input.avi -vcodec copy -acodec copy -ss 00:00:00 -t 00:30:00 output1.avi \
   -vcodec copy -acodec copy -ss 00:30:00 -t 00:30:00 output2.avi

คำถามของฉันคือวิธีการในภายหลังช่วยประหยัดเวลาและหน่วยความจำในการคำนวณหรือไม่


3
เมื่อใช้ "-vcodec copy -acodec copy" มันเร็วมาก :))
Savas Adar

@Antony ทำไมคุณไม่ลองใช้เวลาทั้งสองเวอร์ชัน (และดูที่หน่วยความจำเช่นhtop) และบอกเราว่าคำตอบคืออะไร
AlcubierreDrive

ตัวอย่างแรกทำตามลำดับในขณะที่ตัวอย่างที่สองใช้เธรด ทั้งสองจะทำสิ่งเดียวกันไม่ควรเกิดการเร่งความเร็วที่เห็นได้ชัดเจน แต่เพื่อให้ง่ายขึ้นคุณอาจใช้ ffmpeg stream segmenter muxer: ffmpeg.org/…
Mladen B.

1
ตัวอย่างนี้ดูไม่ถูกต้อง! เอกสาร ffmpeg กล่าวเกี่ยวกับอ็อพชัน -ss: "เมื่อใช้เป็นอ็อพชันอินพุต (ก่อน -i) ให้ค้นหาอินพุตไฟล์นี้เพื่อวางตำแหน่งเมื่อใช้เป็นอ็อพชันเอาต์พุต (ก่อนชื่อไฟล์เอาต์พุต) จะถอดรหัส แต่จะละทิ้งอินพุตจนกว่า การประทับเวลาไปถึงตำแหน่ง " คุณกำลังใช้มันในตำแหน่งเอาต์พุตดังนั้นบรรทัดที่สองของคุณจึงเสียความพยายามในการถอดรหัสและทิ้ง 30 นาทีแรก
Lucian Wischik

1
@LucianWischik แต่การใช้-ssเป็นตัวเลือกการป้อนข้อมูลในการแยกครั้งที่สองอาจไม่ถูกต้องดังนั้นคุณอาจไม่ได้รับการแยกที่ชัดเจน IMO ตัวอย่างโดย OP นั้นถูกต้องกว่า
jiggunjer

คำตอบ:


82

วิกิ ffmpeg จะลิงก์กลับมาที่หน้านี้โดยอ้างอิงถึง "วิธีแบ่งวิดีโออย่างมีประสิทธิภาพ" ฉันไม่มั่นใจว่าหน้านี้จะตอบคำถามนั้นได้ดังนั้นฉันจึงทำตามที่ @AlcubierreDrive แนะนำ ...

echo "Two commands" 
time ffmpeg -v quiet -y -i input.ts -vcodec copy -acodec copy -ss 00:00:00 -t 00:30:00 -sn test1.mkv
time ffmpeg -v quiet -y -i input.ts -vcodec copy -acodec copy -ss 00:30:00 -t 01:00:00 -sn test2.mkv
echo "One command" 
time ffmpeg -v quiet -y -i input.ts -vcodec copy -acodec copy -ss 00:00:00 -t 00:30:00 \
  -sn test3.mkv -vcodec copy -acodec copy -ss 00:30:00 -t 01:00:00 -sn test4.mkv

เอาท์พุตใด ...

Two commands
real    0m16.201s
user    0m1.830s
sys 0m1.301s

real    0m43.621s
user    0m4.943s
sys 0m2.908s

One command
real    0m59.410s
user    0m5.577s
sys 0m3.939s

ฉันทดสอบไฟล์ SD & HD หลังจากรันไม่กี่ครั้งและคณิตศาสตร์เล็กน้อย

Two commands SD 0m53.94 #2 wins  
One command  SD 0m49.63  

Two commands SD 0m55.00  
One command  SD 0m52.26 #1 wins 

Two commands SD 0m58.60 #2 wins  
One command  SD 0m58.61 

Two commands SD 0m54.60  
One command  SD 0m50.51 #1 wins 

Two commands SD 0m53.94  
One command  SD 0m49.63 #1 wins  

Two commands SD 0m55.00  
One command  SD 0m52.26 #1 wins 

Two commands SD 0m58.71  
One command  SD 0m58.61 #1 wins

Two commands SD 0m54.63  
One command  SD 0m50.51 #1 wins  

Two commands SD 1m6.67s #2 wins  
One command  SD 1m20.18  

Two commands SD 1m7.67  
One command  SD 1m6.72 #1 wins

Two commands SD 1m4.92  
One command  SD 1m2.24 #1 wins

Two commands SD 1m1.73  
One command  SD 0m59.72 #1 wins

Two commands HD 4m23.20  
One command  HD 3m40.02 #1 wins

Two commands SD 1m1.30  
One command  SD 0m59.59 #1 wins  

Two commands HD 3m47.89  
One command  HD 3m29.59 #1 wins  

Two commands SD 0m59.82  
One command  SD 0m59.41 #1 wins  

Two commands HD 3m51.18  
One command  HD 3m30.79 #1 wins  

ไฟล์ SD = ไฟล์
HDสตรีมการขนส่ง DVB 1.35GB = สตรีมการขนส่ง DVB 3.14GB

สรุป

คำสั่งเดียวจะดีกว่าถ้าคุณจัดการ HD มันเห็นด้วยกับความคิดเห็นของคู่มือเกี่ยวกับการใช้ -ss หลังจากไฟล์อินพุตเพื่อทำการ 'ค้นหาช้า' ไฟล์ SD มีความแตกต่างเล็กน้อย

เวอร์ชันคำสั่งทั้งสองควรเร็วกว่าโดยการเพิ่ม -ss อื่นก่อนไฟล์อินพุตสำหรับ 'ค้นหาอย่างรวดเร็ว' ตามด้วยการค้นหาช้าที่แม่นยำยิ่งขึ้น


หาก TS มีหลายโปรแกรม (รายการทีวีที่ DVB-T บันทึก) จะแยกได้อย่างไร ตัวอย่างเช่นฉันมีไฟล์ TS ที่มีฟุตบอล + ทำอาหาร + การ์ตูนฉันจะแบ่งไฟล์ TS นี้เป็น 3 ไฟล์ mpg ได้อย่างไร
Dr.jacky

ฉันใช้คำตอบของคุณในคำถามของฉันที่นี่ ( stackoverflow.com/questions/41983940/… ) แต่มันไม่ได้ผลคุณคิดว่าฉันทำอะไรผิด?
utdev

1
ไฟล์ผลลัพธ์ไม่มีวิดีโอ (เฉพาะเสียง) ในกรณีของฉัน หลังจากการทดลองบางอย่างฉันพบจิตวิญญาณ มันจำเป็นต้องระบุที่สำคัญสำหรับ "ไม่แก้ไขที่มีคุณภาพ" -q:v 0เช่นนี้
oklas

19

นี่คือสคริปต์ที่มีประโยชน์ซึ่งจะช่วยให้คุณแยกโดยอัตโนมัติ: สคริปต์สำหรับการแยกวิดีโอโดยใช้ ffmpeg

#!/bin/bash
 
# Written by Alexis Bezverkhyy <alexis@grapsus.net> in 2011
# This is free and unencumbered software released into the public domain.
# For more information, please refer to <http://unlicense.org/>
 
function usage {
        echo "Usage : ffsplit.sh input.file chunk-duration [output-filename-format]"
        echo -e "\t - input file may be any kind of file reconginzed by ffmpeg"
        echo -e "\t - chunk duration must be in seconds"
        echo -e "\t - output filename format must be printf-like, for example myvideo-part-%04d.avi"
        echo -e "\t - if no output filename format is given, it will be computed\
 automatically from input filename"
}
 
IN_FILE="$1"
OUT_FILE_FORMAT="$3"
typeset -i CHUNK_LEN
CHUNK_LEN="$2"
 
DURATION_HMS=$(ffmpeg -i "$IN_FILE" 2>&1 | grep Duration | cut -f 4 -d ' ')
DURATION_H=$(echo "$DURATION_HMS" | cut -d ':' -f 1)
DURATION_M=$(echo "$DURATION_HMS" | cut -d ':' -f 2)
DURATION_S=$(echo "$DURATION_HMS" | cut -d ':' -f 3 | cut -d '.' -f 1)
let "DURATION = ( DURATION_H * 60 + DURATION_M ) * 60 + DURATION_S"
 
if [ "$DURATION" = '0' ] ; then
        echo "Invalid input video"
        usage
        exit 1
fi
 
if [ "$CHUNK_LEN" = "0" ] ; then
        echo "Invalid chunk size"
        usage
        exit 2
fi
 
if [ -z "$OUT_FILE_FORMAT" ] ; then
        FILE_EXT=$(echo "$IN_FILE" | sed 's/^.*\.\([a-zA-Z0-9]\+\)$/\1/')
        FILE_NAME=$(echo "$IN_FILE" | sed 's/^\(.*\)\.[a-zA-Z0-9]\+$/\1/')
        OUT_FILE_FORMAT="${FILE_NAME}-%03d.${FILE_EXT}"
        echo "Using default output file format : $OUT_FILE_FORMAT"
fi
 
N='1'
OFFSET='0'
let 'N_FILES = DURATION / CHUNK_LEN + 1'
 
while [ "$OFFSET" -lt "$DURATION" ] ; do
        OUT_FILE=$(printf "$OUT_FILE_FORMAT" "$N")
        echo "writing $OUT_FILE ($N/$N_FILES)..."
        ffmpeg -i "$IN_FILE" -vcodec copy -acodec copy -ss "$OFFSET" -t "$CHUNK_LEN" "$OUT_FILE"
        let "N = N + 1"
        let "OFFSET = OFFSET + CHUNK_LEN"
done

2
ความคิดเห็นเดียวกันกับคุณสำหรับ SEARAS การเขียนไฟล์แบตช์มีประโยชน์เมื่อจำเป็นจริงๆและเมื่อคุณไม่มีตัวเลือกอื่นให้ใช้เพราะมันไม่สามารถพกพาได้ คุณจะไม่สามารถเรียกใช้สคริปต์เดียวกันบน Windows ได้เช่น เมื่อมีวิธีทั่วไป / พกพามากขึ้นควรหลีกเลี่ยงสคริปต์แบตช์เพื่อประหยัดเวลาที่ต้องใช้ในการพอร์ต เนื่องจาก ffmpeg มีหลายวิธีในการแก้ปัญหานี้วิธีที่เหมาะสมคือการใช้ ffmpeg เพียงอย่างเดียวโดยไม่ต้องใช้สคริปต์
Mladen B.

สคริปต์ที่ดี คุณเขียนมันหรือเปล่า? อยู่บน GitHub หรือไม่ ฉันอยากให้คำแนะนำ :)
เสียง

สำหรับ mp4 ฉากเสียหาย แทนที่สำเนาด้วย: -vcodec libx264 -acodec aac
kishu

8

จากประสบการณ์ของฉันอย่าใช้ ffmpeg ในการแยก / เข้าร่วม MP4Box เร็วและเบากว่า ffmpeg โปรดลอง เช่นถ้าคุณต้องการแบ่งไฟล์ MP4 ขนาด 1400mb ออกเป็นสองส่วน 700mb คุณสามารถใช้ cmdl ต่อไปนี้: MP4Box -splits 716800 input.mp4 เช่นสำหรับการเชื่อมต่อสองไฟล์ที่คุณสามารถใช้ได้:

MP4Box -cat file1.mp4 -cat file2.mp4 output.mp4

หรือหากคุณต้องการแบ่งตามเวลาให้ใช้-splitx StartTime:EndTime:

MP4Box -add input.mp4 -splitx 0:15 -new split.mp4


นี่คือสิ่งที่ฉันต้องการ! เมื่อฉันตัดด้วย ffmpeg คลิปไม่ได้เริ่มต้นบนคีย์เฟรมและมีอาการค้างแปลก ๆ ในตอนท้าย การใช้ MP4Box -splitz ทำเคล็ดลับ!
แมตต์

1
ฉันจะตัดต่อวิดีโอโดยใช้ Mp4Box ด้วยตัวเลขหลายตัวได้อย่างไร ตัวอย่างเช่นฉันต้องมีคลิปย่อยเป็นวินาทีคือ: 5 - 8, 21 - 30, 12 - 18 ดังนั้นฉันต้องการไฟล์วิดีโอเอาต์พุตสามไฟล์
mhndev

และใช้งานง่ายEndTimeกว่า-tมาก
vmassuchetto


2

แนวทางในภายหลังช่วยประหยัดเวลาในการคำนวณและหน่วยความจำหรือไม่?

ไม่มีความแตกต่างอย่างมากระหว่างสองตัวอย่างที่คุณให้มา ตัวอย่างแรกตัดวิดีโอตามลำดับใน 2 ขั้นตอนในขณะที่ตัวอย่างที่สองทำพร้อมกัน (โดยใช้เธรด) จะไม่สังเกตเห็นการเร่งความเร็วเป็นพิเศษ คุณสามารถอ่านเพิ่มเติมเกี่ยวกับการสร้างหลายเอาต์พุตด้วย FFmpeg

ยิ่งไปกว่านั้นสิ่งที่คุณสามารถใช้ได้ (ใน FFmpeg ล่าสุด) คือสตรีมเซ็กเตอร์ muxerซึ่งสามารถ:

เอาต์พุตสตรีมไปยังไฟล์แยกต่างหากจำนวนหนึ่งที่มีระยะเวลาเกือบคงที่ รูปแบบชื่อแฟ้มเอาท์พุทสามารถตั้งค่าในลักษณะคล้ายกับภาพที่ 2


2

นี่คือไฟล์ค้างคาวของ Windows อย่างง่ายที่จะแบ่งไฟล์ขาเข้าออกเป็น 50 ส่วน แต่ละส่วนมีความยาว 1 นาที ขออภัยสำหรับสคริปต์โง่ ๆ ฉันหวังว่ามันจะดีกว่าถ้ามีสคริปต์ windows โง่ ๆ แทนที่จะไม่มีเลย บางทีมันอาจช่วยใครบางคน (อิงตาม "ไฟล์ค้างคาวสำหรับลูป" จากไซต์นี้)

set var=0
@echo off
:start
set lz=
if %var% EQU 50 goto end
if %var% LEQ 9 set lz=0
echo part %lz%%var%
ffmpeg -ss 00:%lz%%var%:00 -t 00:01:00 -i %1 -acodec copy -vcodec copy %2_%lz%%var%.mp4
set /a var+=1
goto start

:end
echo var has reached %var%.
exit

โดยพื้นฐานแล้วนี่คือข้อมูลโค้ดแรกในคำถาม ( ffmpegคำสั่งต่อเนื่องกัน) ที่เขียนซ้ำเป็นลูป สิ่งนี้ไม่ได้ตอบคำถามว่าแนวทางนั้นหรือคำสั่งเดียวจะ "ประหยัดเวลาและความจำในการคำนวณ"
BACON

1

ไม่ได้ทดสอบ ist แต่ดูมีแนวโน้ม:

ตัวแบ่งส่วนกระแสข้อมูลพื้นฐาน

เห็นได้ชัดว่าการแยก AVI ออกเป็นส่วนที่มีขนาดเท่ากันซึ่งหมายความว่าชิ้นส่วนเหล่านี้ไม่ทำให้คุณภาพลดลงหรือเพิ่มหน่วยความจำหรือต้องคำนวณใหม่

นอกจากนี้ยังใช้สำเนาตัวแปลงสัญญาณ - นั่นหมายความว่าสามารถรองรับสตรีมขนาดใหญ่มากได้หรือไม่? เพราะนี่คือปัญหาของฉันฉันต้องการทำลาย avi ของฉันเพื่อที่ฉันจะได้ใช้ตัวกรองเพื่อกำจัดความว้าวุ่นใจ แต่ avi ทั้งหมดทำงานเป็นเวลาหลายชั่วโมง


-1

นี่คือวิธีที่สมบูรณ์แบบในการแบ่งวิดีโอ ฉันเคยทำมาแล้วและมันก็ใช้ได้ดีสำหรับฉัน

ffmpeg -i C:\xampp\htdocs\videoCutting\movie.mp4 -ss 00:00:00 -t 00:00:05 -async 1 C:\xampp\htdocs\videoCutting\SampleVideoNew.mp4 (สำหรับ cmd). shell_exec('ffmpeg -i C:\xampp\htdocs\videoCutting\movie.mp4 -ss 00:00:00 -t 00:00:05 -async 1 C:\xampp\htdocs\videoCutting\SampleVideoNew.mp4')(สำหรับ php)

โปรดปฏิบัติตามนี้และฉันมั่นใจว่าจะทำงานได้อย่างสมบูรณ์


เหตุใดจึงเป็น "วิธีที่สมบูรณ์แบบ" ในการแบ่งวิดีโอ เช่นเดียวกับบรรทัดคำสั่งในคำถามที่คุณผ่าน-iตามด้วยและ-ss -tคำถามคือเกี่ยวกับวิธีแยกหลายเซ็กเมนต์ออกจากไฟล์อินพุตเดียวกันอย่างมีประสิทธิภาพในขณะที่คุณแยกเฉพาะเซ็กเมนต์เดียว ฉันไม่เห็นว่าสิ่งนี้ตอบคำถามได้อย่างไร
BACON

-2

หนึ่งในวิธีที่ง่ายคือการใช้ตัวเลือกตัดกับpublitio API

เมื่อคุณอัปโหลดวิดีโอของคุณแล้วให้ตั้งค่าออฟเซ็ตเริ่มต้นและสิ้นสุดการชดเชยใน url (so_2, eo_2) ดังนี้:

    https://media.publit.io/file/so_2,eo_2/tummy.mp4

สิ่งนี้จะสร้างวิดีโอใหม่ทันทีโดยเริ่มจากวินาทีที่ 2 และความยาว 2 วินาที คุณสามารถแยกวิดีโอด้วยวิธีนี้ได้ตามต้องการ


คำถามคือการถามซึ่งมีประสิทธิภาพมากกว่าสองวิธีในการแยกหลายส่วนจากไฟล์อินพุตด้วยffmpeg. ถ้าคุณไม่มีการเชื่อมต่ออินเทอร์เน็ตที่รวดเร็วจริงๆฉันคิดว่าการอัปโหลดวิดีโอทั้งหมดไปยังบริการคลาวด์จากนั้นดาวน์โหลดผลลัพธ์จะเพิ่มเวลาในการประมวลผลอย่างมาก ดังนั้นแม้ยังไม่ได้ตอบคำถามที่เข้าใกล้กับffmpegมีประสิทธิภาพมากขึ้น
BACON
โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.