ฉันจะใส่วิดีโอให้พอดีกับขนาดที่ต้องการ แต่อย่าอัปโหลดด้วย FFmpeg ได้อย่างไร


13

ฉันต้องใส่วิดีโอให้พอดีกับ 640x360 (สูงสุดที่ผู้เล่นโทรศัพท์ของฉันสามารถรองรับได้) ในขณะที่รักษาอัตราส่วนภาพไว้ แต่ฉันต้องการให้วิดีโอไม่เปลี่ยนแปลงหากมีขนาดเล็กกว่า 640x360 (ไม่ต้องปรับขนาดเลย)

มีวิธีรับพฤติกรรมนี้โดยใช้บรรทัดคำสั่งของ ffmpeg หรือไม่


ฉันไม่คิดว่าสิ่งนี้สามารถทำได้ใน ffmpeg เพียงอย่างเดียว แต่ถ้าคุณยินดีที่จะเขียนสคริปต์มันก็สามารถทำได้อย่างแน่นอน
evilsoup

ฉันได้เขียนสคริปต์ไปแล้ว แต่ฉันต้องการล้างรหัสของฉันในกรณีที่ไม่จำเป็น
sashoalm

อาจเป็นไปได้ด้วยตัวกรองมาตราส่วนที่ใช้ฟังก์ชั่นเช่นmin(…)แต่ง่ายกว่าแน่นอนที่สุดด้วยสคริปต์ง่าย ๆ ที่แยกวิเคราะห์มิติ ดูคำสั่งของฉันที่นี่เพื่อดูตัวอย่างของสิ่งที่สามารถทำได้: superuser.com/questions/547296/…
slhck

คำตอบ:


10

ด้วยเวอร์ชัน ffmpeg ที่ใหม่กว่าคุณสามารถใช้scaleตัวforce_original_aspect_ratioเลือกของตัวกรองได้ ตัวอย่างเช่นเพื่อให้วิดีโอพอดีกับ 1280 × 720 โดยไม่มีการลดอัตราการสุ่มสัญญาณ (ดูโพสต์นี้สำหรับข้อมูลเพิ่มเติม):

ffmpeg -i input.mp4 -filter:v "scale='min(1280,iw)':min'(720,ih)':force_original_aspect_ratio=decrease,pad=1280:720:(ow-iw)/2:(oh-ih)/2" output.mp4

ที่นี่scaleตัวกรองมีขนาด 1280 × 720 หากวิดีโออินพุตมีขนาดใหญ่กว่านั้น หากมีขนาดเล็กก็จะไม่ถูกลดอัตราการสุ่ม padกรองเป็นสิ่งจำเป็นที่จะนำวิดีโอออก 1280 × 720 ในกรณีที่อัตราส่วนหรือขนาดแง่มุมที่แตกต่างจากขนาดเป้าหมาย


ด้วย ffmpeg เวอร์ชั่นเก่าจะมีวิธีแก้ปัญหาที่ค่อนข้างแฮ็ก ก่อนอื่นให้กำหนดความกว้างความสูงและอัตราส่วนของเอาต์พุตของคุณ สิ่งนี้จะช่วยเราในการพิมพ์

width=640; height=360
aspect=$( bc <<< "scale=3; $width / $height") # <= floating point division

ตอนนี้เราจะใช้คำสั่งตัวกรอง super complex ที่Jim Worrall เขียนไว้ :

ffmpeg -i input.mp4 -vf "scale = min(1\,gt(iw\,$width)+gt(ih\,$height)) * (gte(a\,$aspect)*$width + \
lt(a\,$aspect)*(($height*iw)/ih)) + not(min(1\,gt(iw\,$width)+gt(ih\,$height)))*iw : \
min(1\,gt(iw\,$width)+gt(ih\,$height)) * (lte(a\,$aspect)*$height + \
gt(a\,$aspect)*(($width*ih)/iw)) + not(min(1\,gt(iw\,$width)+gt(ih\,$height)))*ih" \
output.mp4

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


1
+1 แต่นั่นเป็นคำสั่งที่น่ากลัวอย่างแท้จริง: P
evilsoup

ฉันรู้ใช่มั้ย ฉันใช้เวลาสิบนาทีในการพยายามแบ่งมันออกเป็นส่วนต่างๆแล้วใส่ค่าบางอย่าง แต่ฉันก็ยอมแพ้ มันเก่าไปหน่อยและบางทีมันอาจเป็นไปได้ที่จะเขียนมันให้กระชับกว่านี้
slhck

14

เวอร์ชันที่อ่านได้มากขึ้นมีลักษณะดังนี้:

-filter_complex "scale=iw*min(1\,min(640/iw\,360/ih)):-1"

640 / iw เป็นตัวประกอบสเกลแนวนอนและ 360 / ih เป็นตัวประกอบสเกลแนวตั้ง

คุณต้องการให้พอดีกับภาพที่ปรับขนาดภายในกล่องผลลัพธ์และรักษาอัตราส่วน (ที่เก็บข้อมูล) คุณทำได้โดยเลือกตัวประกอบสเกลที่เล็กที่สุดด้วยฟังก์ชันขั้นต่ำ: ขั้นต่ำ (640 / iw, 360 / ih)

คุณต้องการป้องกันการลดอัตราการสุ่ม (เช่นปัจจัยการปรับ> 1.0) เพื่อให้คุณเพิ่มฟังก์ชั่นขั้นต่ำอื่น: ขั้นต่ำ (1, ขั้นต่ำ (640 / iw, 360 / ih))

ขั้นต่อไปคือการคำนวณความละเอียดเอาต์พุตโดยการคูณสเกลปัจจัยกับอินพุตความกว้างและอินพุตความสูง:
เอาท์พุทไวด์ ธ = iw * นาที (1, นาที (640 / iw, 360 / ih))
เอาท์พุทสูง = ih * ขั้นต่ำ (1, ขั้นต่ำ (640 / iw, 360 / ih))

ขั้นตอนสุดท้ายคือการสร้างคำสั่งตัวกรอง ไม่จำเป็นต้องระบุความสูงของเอาต์พุตคุณสามารถระบุ -1 และ ffmpeg จะรักษาอัตราส่วนภาพไว้โดยใช้ตัวคูณมาตราส่วนเดียวกันกับความกว้าง


A + ทำงานนอกกรอบ โซลูชันของคำตอบที่เลือกไม่ได้รักษาอัตราส่วนกว้างยาว มันบีบเฟรม
287352

5

ฉันมีปัญหาเดียวกัน แต่แก้ไขด้วยการปรับวิดีโอให้เหมาะสมในรูปสี่เหลี่ยมจตุรัส 640x640 (เพราะวิดีโอแนวตั้งที่ทำด้วยสมาร์ทโฟน)

ดังนั้นการใช้ตรรกะimmerziและการวิจัยบางอย่างฉันท้ายนี้

-vf "scale=iw*min(1\,if(gt(iw\,ih)\,640/iw\,(640*sar)/ih)):(floor((ow/dar)/2))*2"

ส่วนสุดท้ายคือการมีความสูงหารด้วย 2 ที่ต้องการโดยเข้ารหัสหลาย

โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.