การปรับขนาดวิดีโอด้วย ffmpeg / avconv เพื่อให้พอดีกับเครื่องเล่นขนาดคงที่


65

ฉันมีเครื่องเล่นวิดีโอ html 5 ซึ่งมีความกว้าง 700px สูง 400px ฉันพยายามใช้avconvเพื่อใช้ ffmpeg เพื่อปรับขนาด (ในขณะที่รักษาอัตราส่วนภาพ) และทำให้แน่ใจว่ามันเหมาะกับเครื่องเล่นของฉัน

อินพุตอาจเป็นไฟล์ขนาดใดก็ได้ดังนั้นฉันจำเป็นต้องปรับขนาดใหญ่ขึ้น แต่จัดให้เล็กลงด้วยแถบสีดำ จนถึงตอนนี้ฉันได้ลองแล้ว: -sและ-aspectฉันเคยเห็นpadการใช้งาน-vfสวิตช์ แต่ไม่เข้าใจว่ามันทำงานได้ดีพอที่จะได้รับสิ่งที่ฉันต้องการ

ภาพ

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

คำสั่ง avconv:

avconv -y -i control.avi -vcodec libx264 -b 2000k -bufsize 20M -acodec aac -strict experimental -ar 44100 -ab 256k bigbuck_out.mp4


4
ฉันจะเขียนคำตอบในภายหลัง แต่ฉันคิดว่าฉันจะพูดถึงสิ่งต่อไปนี้: การเข้ารหัสวิดีโออีกครั้งเพื่อเพิ่มเสาหลักที่คงที่ - หรือตู้ไปรษณีย์เป็นความคิดที่แย่มาก ไม่เพียง แต่คุณจะสูญเสียคุณภาพในกระบวนการนั้น (หรือเพิ่มขนาดไฟล์โดยไม่จำเป็น) คุณจะไม่สามารถกำจัดแถบในภายหลังได้ ผู้เล่นของคุณควรดูแลและปรับขนาดวิดีโอขณะที่แสดง กรณีการใช้งานของคุณคืออะไรถ้าฉันอาจถาม?
slhck

เราซ่อนไฟล์ต้นฉบับไว้ในที่ฝากข้อมูล S3 ดังนั้นจึงไม่มีปัญหาและเราเข้ารหัสอีกครั้งเนื่องจากเรายอมรับขอบเขตวิดีโอประเภทใหญ่ ๆ ทั้งหมดเหล่านี้ต้องจบลงด้วยไฟล์ h.264 mp4 ที่เหมาะสำหรับการสตรีมผ่าน เบราว์เซอร์ ดังนั้นคุณแนะนำให้ปรับขนาดวิดีโอแล้วสร้าง html / css pillar / letterboxes? ขอบคุณ
Jamie Taylor

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

@slhck ฉันกำลังพิจารณาด้วยพรของคุณฉันจะทำให้มัน
Jamie Taylor

คำตอบ:


52

วิธีการที่ง่ายคือการใช้force_original_aspect_ratioตัวเลือกในกรองตะกรัน

ภาพต้นฉบับ
ภาพต้นฉบับ แสดงวิดีโออัตราส่วนกว้าง 640x480, 4: 3

ในตัวอย่างเหล่านี้ภาพต้นฉบับจะถูกปรับอัตราส่วนให้พอดีกับเอาต์พุตอัตราส่วนภาพ 16: 9 ในขณะที่รักษาอัตราส่วนภาพต้นฉบับไว้ ในการทำเช่นนี้คุณสามารถ:

Pillarbox หรือตู้ไปรษณีย์

ภาพ pillarboxed
ภาพ Pillarboxed ติดตั้งอินพุต 640x480 (4: 3) เข้ากับเอาต์พุต 1280x720 (16: 9)

ffmpeg -i input -vf "scale=1280:720:force_original_aspect_ratio=decrease,pad=1280:720:(ow-iw)/2:(oh-ih)/2" output
  • นี่จะยกระดับภาพ หากคุณต้องการหลีกเลี่ยงการลดอัตราการสุ่มสัญญาณดูตัวอย่างด้านล่าง

  • การทำ Letterboxing จะเกิดขึ้นแทนหากอัตราส่วนภาพเข้ากว้างกว่าอัตราส่วนภาพออก ตัวอย่างเช่นอินพุตที่มีอัตราส่วนกว้างยาว 2.35: 1 พอดีกับเอาต์พุต 16: 9 จะส่งผลให้มีการทำกล่องจดหมาย

เหมือนด้านบน แต่ไม่มีการลดอัตราการสุ่มสัญญาณ

ไม่มีการลดอัตราการสุ่ม
อินพุต 640x480 (4: 3) เป็นเอาต์พุต 1280x720 (16: 9) โดยไม่มีการลดอัตราการสุ่มสัญญาณ

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

พืชผล

ป้อนคำอธิบายรูปภาพที่นี่
ภาพที่ครอบตัด อัตราส่วนอินพุต 4: 3, อัตราส่วนเอาต์พุต 16: 9

ffmpeg -i input -vf "scale=1280:720:force_original_aspect_ratio=increase,crop=1280:720" output

และสำหรับฉันที่จะเพิ่มการเติมเปล่า?
Tiago Ferezin

@TiagoFerezin "เติมว่างเปล่า" คืออะไร
llogan

ขอโทษด้วยเติมสีอื่นแทนสีดำเช่น
Tiago Ferezin

2
@TiagoFerezin อ่าใช่ ง่ายต่อการทำ ในตัวอย่างที่ใช้แผ่นกรองคุณสามารถเพิ่มcolorตัวเลือกเช่นpad=1280:720:(ow-iw)/2:(oh-ih)/2:color=red(หรือคุณสามารถใช้เลขฐานสิบหกได้หากต้องการ) ดูรายชื่อของสี
llogan

61

นี่คือคำสั่งที่จะเพิ่ม pillar- หรือ letterboxing สำหรับความกว้างเอาต์พุตคงที่ มันยาวไปหน่อย แต่คุณจะต้องระบุช่องว่างภายใน

ครั้งแรกในเปลือกของคุณกำหนดความกว้างและความสูงออก:

width=700
height=400

จากนั้นรันคำสั่ง:

ffmpeg -i in.mp4 -filter:v "scale=iw*min($width/iw\,$height/ih):ih*min($width/iw\,$height/ih), pad=$width:$height:($width-iw*min($width/iw\,$height/ih))/2:($height-ih*min($width/iw\,$height/ih))/2" out.mp4

สิ่งนี้ถูกถอดออกไปยังสิ่งจำเป็นพื้นฐานที่จำเป็นในการปรับขนาดและเพิ่มแผ่น - เพิ่มตัวเลือกวิดีโอและเสียงอื่น ๆ ของคุณตามที่เห็นสมควร โปรดทราบว่าตัวเลขwidthและheightต้องหารด้วย 2 เพื่อให้ตัวแปลงสัญญาณส่วนใหญ่ทำงานได้

นี่คือคำอธิบายของสิ่งที่เกิดขึ้น:

  • Scaling:
    • ก่อนอื่นเราต้องหาว่าจะขยายสเกลตามความกว้างหรือความสูง
    • ในการทำเช่นนี้เราแบ่งความกว้างของเอาต์พุตตามความกว้างของอินพุตและความสูงของเอาต์พุตตามความสูงของอินพุต สิ่งนี้จะทำให้เรามีตัวคูณสเกลสำหรับแต่ละมิติ
    • จากนั้นเราตรวจสอบว่าอันไหนที่ต่ำกว่า (พร้อมmin()) และเลือกเฉพาะปัจจัยนั้นสำหรับการปรับขนาด
    • สุดท้ายเราคูณทั้งความกว้างและความสูงของอินพุตด้วยตัวคูณนั้น ( iw*min(…):ih*min(…))
  • การขยายความ:
    • $width:$height คือความกว้างและความสูงของเอาต์พุต
    • ในการหาตำแหน่งที่จะวางวิดีโอที่เกิดขึ้นเราจำเป็นต้องลบความกว้างที่ปรับขนาดจากความกว้างสูงสุดออกและความสูงที่ปรับขนาดจากความสูงออกสูงสุด
    • ความกว้างและความสูงที่ปรับสัดส่วนเป็นนิพจน์จากscaleตัวกรอง
    • เราหารผลที่ได้ด้วย 2 เพื่อเพิ่มเส้นขอบทั้งสองข้าง

3
@JamieTaylor พิจารณาเพิ่ม-movflags +faststartตัวอย่าง slhck ของ มันจะช่วยให้วิดีโอที่คุณดาวน์โหลดอย่างต่อเนื่องเริ่มเล่นก่อนที่จะดาวน์โหลดได้อย่างสมบูรณ์และยังดูคู่มือการเข้ารหัส FFmpeg และ x264และFFmpeg และ AAC คู่มือการเข้ารหัสสำหรับคำแนะนำและตัวอย่างการเข้ารหัสเพิ่มเติม
llogan

คุณสามารถทำให้แผ่นกรองสั้นลงฉันคิดว่า:pad=$width:$height:(ow-iw)/2:(oh-ih)/2"
jdi

1
@jdi นี้จะไม่ทำงานถ้าคุณกำลัง downscaling ow-iwเพราะมันจะส่งผลในเชิงลบสำหรับค่า
slhck

ขอบคุณสำหรับจุดเริ่มต้น! อย่างไรก็ตามเพื่อให้ได้อัตราส่วนภาพที่เหมาะสมสำหรับวิดีโอที่มีอัตราส่วนภาพตัวอย่าง! = 1 ทุก ๆ เหตุการณ์ของ "iw" จะต้องคูณด้วย "sar" ดังนั้นจึงควรแทนที่ "iw" ทุกครั้งด้วย "(sar * iw)" ในนิพจน์ตัวกรองใช้งานได้สำหรับฉัน
schieferstapel

@slhck เฮ้ฉันพยายามใช้ Android แต่ดูเหมือนว่ามันจะไม่ทำงานคุณสามารถช่วยฉันด้วย !!! ffmpeg -i input.mp4 -filter: v scale = 640 * นาที (700 / 640,400 / 360): 360 * นาที (700 / 640,400 / 360), pad = 700: 400: (700-640 * นาที (700 / 640,400 / 360)) / 2: (400-360 * นาที (700 / 640,400 / 360)) / 2 เอาท์พุท. mp4
Nisarg

8

ดูเหมือนว่าคุณจะต้องทำในสามขั้นตอน:

  1. ตรวจสอบอัตราส่วนภาพเข้า
  2. ปรับขนาดวิดีโอด้วย DAR> 7/4 width-wise (เปลี่ยนความกว้างเป็น 700 และปรับขนาดความสูงเพื่อรักษาอัตราส่วนภาพ) และปรับขนาดวิดีโอด้วย DAR <7/4 height-wise
  3. วางแผ่นวิดีโอเพื่อให้พอดีกับพื้นที่ 700: 400

FFmpeg / avconv สามารถทำการปรับ / ขยายด้วยตัวกรองวิดีโอในขั้นตอนเดียวการแปลงรหัสเพียงครั้งเดียว ตัวอย่างเช่นในการถ่ายวิดีโอ 16: 9 ให้ปรับขนาดไวด์ ธ จากนั้นเลือกผลการค้นหา:

ffmpeg -i input.avi -filter:v 'scale=700:-1,pad=700:400:(ow-iw)/2:(oh-ih)/2' \
-c:v libx264 -b:v 2000k -bufsize 20M -c:a aac -strict experimental -ar 44100 -b:a 256k output.mp4

... แต่สำหรับขั้นตอนแรก (การตรวจจับอัตราส่วนภาพและเปรียบเทียบกับ 7: 4 ที่คุณต้องการ) คุณจะต้องใช้สคริปต์บางอย่าง

ffprobe input.avi 2>&1 | sed -n '/Video:/s/.*DAR \([0-9]*:[0-9]*\)].*/\1/p'

... จะทำให้คุณได้สัดส่วนวิดีโอซึ่งจะมีลักษณะเช่น '16: 9 'หรือ' 4: 3 ' ในสคริปต์ทุบตีฉันจะใช้สิ่งที่ชอบ:

#!/bin/bash

##  Get the aspect ratio in the form x/y
dar=$(ffprobe test0.mp4 2>&1 | sed -n '/Video:/s/.*DAR \([0-9]*:[0:9]*\)].*/\1/p' | sed 's|:|/|')
##  use bc to do x/y*100 (bash can't handle floats)
DAR=$(bc <<< 'scale=2; $dar*100')

##  ${DAR%.00} will remove the trailing .00 left by bc
if [ ${DAR%.00} -ge 175 ]; then
    ffmpeg -i "$1" -filter:v 'scale=700:-1,pad=700:400:(ow-iw)/2:(oh-ih)/2' \
    -c:v libx264 -b:v 2000k -bufsize 20M -c:a aac -strict experimental -ar 44100 -b:a 256k "${1%.*}.mp4
else
    ffmpeg -i "$1" -filter:v 'scale=-1:400,pad=700:400:(ow-iw)/2:(oh-ih)/2' \
    -c:v libx264 -b:v 2000k -bufsize 20M -c:a aac -strict experimental -ar 44100 -b:a 256k "${1%.*}.mp4
fi

exit 0

แน่นอนคุณจะต้องปรับให้เข้ากับความต้องการของคุณ


1
เป็นไปได้ที่จะทำอย่างนั้นในขั้นตอนเดียวดูคำตอบของฉัน
slhck

@slhck ตอนนี้มันง่ายกว่า ดูคำตอบด้วยกีตาร์ - กระบอก
llogan

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