วิธีการลบ / ตัดต่อวิดีโอ / คลิปเสียงด้วยระยะเวลาที่ไม่รู้จัก?


19

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

ฉันใช้โค้ดนี้เพื่อเพิ่มเอฟเฟ็กต์เฟด / เอ้าท์บนคลิปที่มีระยะเวลาที่รู้จัก:

ffmpeg -i clip.mp4 -filter:v 'fade=in:0:30,fade=out:9650:30' -c:v libx264 -crf 22 -preset veryfast -c:a copy fadeInOut.mp4

คำถามสองข้อของฉันคือ:

  1. ฉันจะลบเสียงเข้า / ออกพร้อมกันได้อย่างไร
  2. ffmpeg สามารถหาระยะเวลาของคลิปได้โดยอัตโนมัติและได้รับการบอกเพียงแค่เฟรมหลุด 30 เฟรมสุดท้ายหรือไม่

ขอบคุณ!

คำตอบ:


15

# 1ในการลบเสียงเข้า / ออกพร้อมกัน:

ffmpeg -i clip.mp4 -vf 'fade=in:0:30,fade=out:960:30'
                   -af 'afade=in:st=0:d=1,afade=out:st=32:d=1'
       -c:v libx264 -crf 22 -preset veryfast fadeInOut.mp4

ครั้ง afade อยู่ในไม่กี่วินาที

# 2โดยอัตโนมัติ ไม่ แต่ดูวิธีแก้ปัญหาด้านล่าง

คุณสามารถรัน ffprobe ก่อนเพื่อรับช่วงเวลา

ffprobe -i clip.mp4 -show_entries stream=codec_type,duration -of compact=p=0:nk=1

คุณจะได้รับสิ่งนี้:

video|13.556000
audio|13.816000

จากนั้นคุณสามารถใช้ด้านบนเพื่อวางจางหาย เวลาเหล่านี้เป็นวินาที

วิธีแก้ปัญหา

ffmpeg -i clip.mp4 -sseof -1 -copyts -i clip.mp4 -filter_complex
       "[1]fade=out:0:30[t];[0][t]overlay,fade=in:0:30[v];
        anullsrc,atrim=0:2[at];[0][at]acrossfade=d=1,afade=d=1[a]"
       -map "[v]" -map "[a]" -c:v libx264 -crf 22 -preset veryfast -shortest fadeInOut.mp4

FFmpeg มีsseofตัวเลือกที่อนุญาตให้หนึ่งค้นหาอินพุตจากจุดสิ้นสุด เราสามารถใช้สิ่งนั้นเพื่อบรรลุเป้าหมาย ดังนั้นเราจึงป้อนข้อมูลเข้าสองครั้งโดยครั้งที่ 2 จะนำเข้าเฉพาะวินาทีสุดท้าย เราบอก FFmpeg เพื่อรักษา timestamps ดังนั้น ffmpeg จะรักษาตำแหน่งชั่วคราวของส่วนหางนี้

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

สำหรับเสียงเราสร้างเสียงดัมมี่เปล่า ๆ ที่มีระยะเวลา 2 วินาทีจากนั้นนำเสียงไขว้จากเสียงหลักไปใช้กับเสียงจำลองนี้ เนื่องจากเสียงที่ 2 ว่างเปล่านี่เป็นผลมาจากการหายไปของอินพุตหลัก -shortestจะถูกเพิ่มออกจากบางส่วนของเสียงหุ่นหลังจาก Crossfade ได้เกิดขึ้น


สิ่งนี้ทำให้เกิดข้อผิดพลาด "ไม่มีตัวกรองดังกล่าว!" สำหรับตัวกรองเสียง
felwithe

1
มีตัวกรองเสียง 4 ตัวที่ใช้ อันไหน? เรียกใช้คำสั่งของคุณด้วยการ-reportเพิ่มและแบ่งปันรายงาน
Gyan

7

มันเป็นการแฮ็คที่แย่มาก แต่สิ่งนี้อาจใช้ได้ถ้าทุกอย่างที่คุณต้องการคือเสียงจางหายเข้า / ออก แต่ไม่รู้ว่าคลิปจะยาวแค่ไหน:

ffmpeg -i input.mp4 -filter_complex "afade=d=0.5, areverse, afade=d=0.5, areverse" output.mp4

[แก้ไข 2019-07-24: โปรดทราบว่าโซลูชันนี้ไม่ดีสำหรับโซลูชั่นสตรีมมิ่งเนื่องจากต้องใช้การประมวลผลเต็มแทร็กก่อนที่จะสามารถสตรีมไบต์แรก]

ตัวเลือกอื่นที่ฉันจะใช้acrossfadeกับแทร็กเงียบ:

ffmpeg -i input.mp4 -filter_complex "aevalsrc=0:d=0.6 [a_silence]; [0:a:0] [a_silence] acrossfade=d=0.6" output.mp4

3
อันที่จริงแล้วมันสวยหรู :-)
bk138

มันใช้งานได้ดี คุณช่วยอธิบายวิธีการทำงานได้ไหม พยายามทำความเข้าใจกับเอกสาร ..
oberhamsi

1
@oberhamsi: ตัวเลือกที่ 1: ตัวกรองแรกเพิ่มจางที่จุดเริ่มต้นของแทร็ก จากนั้นจะย้อนกลับเสียงและเพิ่มจางหายไปอีกในตอนเริ่มต้น (ซึ่งจริงๆแล้วเป็นจุดสิ้นสุด) ในที่สุดแทร็กจะกลับด้านอีกครั้ง ตัวเลือกที่ 2 สร้างแทร็กที่เงียบเป็นเวลา 0.6 วินาทีและข้ามมันเป็นระยะเวลาเดียวกันกับแทร็กดั้งเดิม ตัวกรองทั้งหมดและการใช้งานมีการบันทึกไว้ที่นี่: ffmpeg.org/ffmpeg-filters.html (แม้ว่าฉันต้องยอมรับว่ามันเป็นความลับเล็กน้อย)
marekventur

3

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

#!/bin/bash

f="$*" # all args
p="${f##*/}" # file
fn="${p%.*}" # name only
e="${p##*.}" # extension

echo
echo $f
echo $p
echo $fn
echo $e
echo

read -e -p "Number of seconds of fade-out: " -i 1 sec # prompt for fade duration in seconds

r=$(ffprobe -show_streams "$f" 2> /dev/null | grep r_frame_rate | head -1 | cut -d \= -f 2) # frame rate
let "frames = $r * $sec" # duration of fade as number of frames
echo $r
echo $sec
echo $frames
lf=$(ffprobe -show_streams "$f" 2> /dev/null | grep nb_frames | head -1 | cut -d \= -f 2) # total number of frames
let "lf = $lf - $frames" # initial frame to start fade at

ffmpeg -loglevel quiet -i "$f" -vf fade=out:$lf:$frames -r $r -vcodec libx264 -preset slow -crf 12 -bf 2 -flags +cgop -pix_fmt yuv420p -acodec copy "$fn $sec sec fade-out.$e"
open "$fn $sec sec fade-out.$e"

จางหายไปต้องเข้ารหัสใหม่เพื่อใช้crfค่าต่ำสำหรับlibx264ให้เข้ารหัสคุณภาพสูง ความคิดเห็นควรอธิบายทุกอย่างอื่น


คำตอบของคำถาม 2 คือใช่ดังก้อง! -> มันยังไม่ Q คือCan ffmpeg หาระยะเวลาโดยอัตโนมัติ ...แต่คุณเขียนสคริปต์ที่รันคำสั่ง ff * หลายคำสั่งเพื่อทำมัน มีประโยชน์สำหรับระบบ * nix
Gyan

ฉันเห็นดังนั้นคุณยืนยันว่าคำตอบของคุณยังถูกต้องหรือไม่ ถ้าคุณทำตามสคริปต์ของฉันคุณจะเห็นว่ามันไม่จริงautomatically figure out the durationใช้ซึ่งมีการติดตั้งffprobe ffmpegใครบอกอะไรเกี่ยวกับข้อ จำกัด เกี่ยวกับจำนวนของคำสั่งหรือ*nix? ดูเหมือนว่า OP กำลังใช้เวอร์ชันของ UNIX ไม่.exeอยู่ในffmpegคำสั่ง ตัวผมเองกำลังใช้OS Xซึ่งถูกสร้างขึ้นบนแต่ไม่ได้เป็นUNIX UNIX
hmj6jmh

1
* ถ้าคุณทำตามสคริปต์ของฉันคุณจะเห็นว่ามันจะคิดออกโดยอัตโนมัติจริง ๆ - -> สคริปต์ของคุณทำอยู่ ffmpeg ไม่ได้
Gyan

แต่ffprobeเป็นส่วนสำคัญของการffmpegกระจาย คุณกำลังเลือกที่ nits เพื่อบันทึกหน้า IMO
hmj6jmh

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