FFMPEG (libx264)“ ความสูงไม่หารด้วย 2”


188

ฉันพยายามเข้ารหัสวิดีโอ. mp4 จากชุดเฟรมโดยใช้ FFMPEG โดยใช้ตัวแปลงสัญญาณ libx264

นี่คือคำสั่งที่ฉันใช้:

/usr/local/bin/ffmpeg -r 24 -i frame_%05d.jpg -vcodec libx264 -y -an video.mp4

บางครั้งฉันได้รับข้อผิดพลาดต่อไปนี้:

[libx264 @ 0xa3b85a0] height not divisible by 2 (520x369)

หลังจากค้นหาไปเล็กน้อยดูเหมือนว่าปัญหามีบางอย่างเกี่ยวกับอัลกอริธึมการปรับสเกลและสามารถแก้ไขได้โดยการเพิ่มอาร์กิวเมนต์ -vf

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


@AleksandrDubinsky แต่คำตอบของ LordNeckbeard ไม่ได้รักษาความกว้างและความสูงดั้งเดิมไว้ที่นี่เราต้องระบุความกว้างหรือความสูงด้วยตนเอง .. และถ้าใช้ขนาด -vf = -2: ih หรือ -vf scale = iw: -2 สิ่งนี้จะไม่ ทำงานได้ถ้าทั้งความสูงและความกว้างไม่เท่ากัน .. โปรดอธิบายว่าคำตอบนั้นดีที่สุดได้อย่างไร .. ขอบคุณ
varmashrivastava

1
@varmashrivastava เอาละวิธีการทำงานของ SO ก็คือในตอนแรกอาจมีคำถามหนึ่งข้อจากนั้น Google ก็ส่งคนจำนวนมากด้วยคำถามที่แตกต่างกันซึ่งเป็นผู้ที่แย่งหน้าเว็บ มันคือสิ่งที่มันเป็นพยายามที่จะไม่ต่อสู้ คำตอบที่ถูกต้องสำหรับคำถามต้นฉบับคือคำตอบ-vf pad="width=ceil(iw/2)*2:height=ceil(ih/2)*2"นั้นไม่ใช่แม้แต่คำตอบเดียว คำตอบที่ถูกต้องสำหรับคำถามของคนอื่นคือของ LordNeckbeard
Aleksandr Dubinsky

@varmashrivastava ฉันได้ดำเนินการต่อไปและแก้ไขคำตอบแรก หวังว่ามันจะไม่ได้รับการบุกทำลายโดยตัวดัดแปลง
Aleksandr Dubinsky

@AleksandrDubinsky ขอบคุณ .. และผู้ใช้สามารถใช้"scale="แทน"pad="ถ้าเขา / เธอไม่ต้องการพิกเซล padding colured?
varmashrivastava

คำตอบ:


269

คำตอบสำหรับคำถามเดิมที่ไม่ต้องการปรับขนาดวิดีโอคือ:

-vf "pad=ceil(iw/2)*2:ceil(ih/2)*2"

คำสั่ง:

ffmpeg -r 24 -i frame_%05d.jpg -vcodec libx264 -y -an video.mp4 -vf "pad=ceil(iw/2)*2:ceil(ih/2)*2"

โดยพื้นฐานแล้ว. h264 ต้องการขนาดที่เท่ากันดังนั้นตัวกรองนี้จะ:

  1. หารความสูงและความกว้างดั้งเดิมด้วย 2
  2. ปัดเศษขึ้นเป็นพิกเซลที่ใกล้ที่สุด
  3. คูณด้วย 2 อีกครั้งทำให้มันเป็นเลขคู่
  4. เพิ่มพิกเซลแพ็ดดิ้งสีดำจนถึงจำนวนนี้

:color=whiteคุณสามารถเปลี่ยนสีของการขยายโดยการเพิ่มพารามิเตอร์ตัวกรอง ดูเอกสารของแผ่น


3
มันไม่ใช่ข้อผิดพลาด ไม่สำคัญว่าคุณจะไม่ทำการปรับขนาดเนื่องจากเอาต์พุตจะสืบทอดขนาดเฟรมของอินพุต
llogan

5
สำหรับบันทึกฉันเพิ่งทำบางสิ่งที่ฉันสร้างวิดีโอจากภาพและใช้ yuvj444p เป็นรูปแบบพิกเซล มันไม่สนใจขนาดของวิดีโอ จากนั้นฉันก็ต้องแปลงมันให้เป็น yuv420p จากนั้นมันก็ดูแลขนาดวิดีโอ ฉันค้นหา yuv420p บนวิกิพีเดียฉันคิดว่ามันเป็นรูปแบบสีหลายพิกเซลที่ต้องการให้ภาพมีขนาดเฉพาะ ไม่แน่ใจว่าทำไมมันถึงมีการบีบอัด
lahwran

7
คุณน่าจะดีกว่าการใช้แผ่นแทนขนาดเพื่อเพิ่มแถว / คอลัมน์สีดำ การปรับขนาดภาพขึ้นหนึ่งพิกเซลจะทำให้ภาพเบลอ
Glenn Maynard

5
@NickeManarin กรองนี้ควรทำงานเพื่อเพิ่ม 1 -vf pad="width=iw:height=ih+1:x=0:y=0:color=white"พิกเซลของการขยายสีขาวเพื่อมิติแนวตั้งกับวิดีโอในตำแหน่งบนซ้าย: เอกสารแผ่น ffmpeg อยู่ที่นี่: ffmpeg.org/ffmpeg-filters.html#pad-1
Mark Berry

4
ต่อไปนี้เป็นวิธีแก้ไขปัญหาที่เพิ่มพิกเซลของการเติมเต็มในส่วนข้อมูลที่แปลก-vf pad="width=ceil(iw/2)*2:height=ceil(ih/2)*2"เท่านั้น:
danneu

250

เพียงแค่ใช้ -2

จากเอกสารตัวกรองสเกล :

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

ตัวอย่าง

ตั้งค่าความกว้างเป็น 1280 และความสูงจะถูกคำนวณโดยอัตโนมัติเพื่อคงอัตราส่วนไว้และความสูงจะหารด้วย 2:

-vf scale=1280:-2

เหมือนด้านบน แต่มีความสูงที่ประกาศไว้แทน ออกความกว้างที่จะจัดการโดยตัวกรอง:

-vf scale=-2:720

"หารด้วย 2"

ตามที่ x264 ต้องการ "หารด้วย 2 สำหรับความกว้างและความสูง" เป็นสิ่งจำเป็นสำหรับ YUV 4: 2: 0 chroma เอาต์พุตย่อย 4: 2: 2 จะต้อง "หารด้วย 2 สำหรับความกว้าง" และ 4: 4: 4 ไม่มีข้อ จำกัด เหล่านี้ อย่างไรก็ตามผู้เล่นที่ไม่ใช่ FFmpeg ส่วนใหญ่สามารถถอดรหัส 4: 2: 0 ได้อย่างถูกต้องเท่านั้นนั่นคือเหตุผลที่คุณมักเห็นffmpegคำสั่งพร้อม-pix_fmt yuv420pตัวเลือกเมื่อแสดงผลวิดีโอ H.264

ข้อแม้

น่าเสียดายที่คุณไม่สามารถใช้ได้-2กับทั้งความกว้างและความสูง แต่หากคุณระบุหนึ่งมิติแล้วการใช้-2เป็นโซลูชันที่ง่าย


14
ฉันคิดว่า tihis ควรถูกทำเครื่องหมายเป็นคำตอบที่ถูกต้องเพราะไม่มี "กลอุบาย" ที่เกี่ยวข้อง ที่จะ
โหวต

1
ทำไมถึง-vf scale=-2:-2ไม่ทำงาน ในกรณีของฉันฉันต้องการรักษาขนาดไฟล์ดั้งเดิมให้มากที่สุด -vf scale=-2:ihสิ่งที่ทำงานสำหรับฉันคือ แต่มันจะไม่ทำงานหากทั้ง h / w ไม่เท่ากัน
ปาสกาล

2
@tuner ค่าผลลัพธ์-2ขึ้นอยู่กับค่าที่ประกาศของส่วนข้อมูลอื่น
llogan

3
ในกรณีของฉันนี่ทำให้ฉันมีข้อผิดพลาดต่อไปนี้: Size values less than -1 are not acceptable.แต่คำตอบจาก @Zbyszek ทำงานได้อย่างสมบูรณ์
Julien

1
@Julien ที่ไม่ ffmpegคุณสามารถดาวน์โหลดสร้างแบบคงที่
llogan

64

หากคุณต้องการตั้งค่าความกว้างของเอาต์พุตและมีเอาต์พุตในอัตราส่วนเดียวกันกับต้นฉบับ

scale=720:-1 

และไม่ให้ตกอยู่กับปัญหานี้จากนั้นคุณสามารถใช้

scale="720:trunc(ow/a/2)*2"

(สำหรับผู้ที่ค้นหาวิธีการกำหนดขนาด)


16
และสำหรับความสูงคงที่ก็คือscale="trunc(oh*a/2)*2:720"
ทอม

20

มีปัญหากับการ scaleแก้ปัญหาที่นี่คือพวกเขาบิดเบือนภาพ / วิดีโอต้นฉบับซึ่งแทบไม่เคยเป็นสิ่งที่คุณต้องการ

แต่ฉันได้พบทางออกที่ดีที่สุดคือการเพิ่มแผ่น 1 พิกเซลให้กับมิติที่แปลก (โดยค่าเริ่มต้น pading เป็นสีดำและยากที่จะสังเกตเห็น)

มีปัญหากับเรื่องอื่น ๆ padแก้ปัญหาก็คือพวกเขาไม่ได้พูดเกินขอบเขตโดยพลการเพราะพวกเขามักจะรอง

วิธีแก้ปัญหานี้จะเพิ่มแผ่นความละเอียด 1 พิกเซลให้กับความสูงและ / หรือความกว้างหากมันแปลก:

-vf pad="width=ceil(iw/2)*2:height=ceil(ih/2)*2"

มันเหมาะอย่างยิ่งเพราะมันทำสิ่งที่ถูกต้องอยู่เสมอแม้ไม่จำเป็นต้องมีช่องว่างภายใน


โซลูชันสเกลจะเปลี่ยนจำนวนพิกเซลทีละ 1 เป็นอย่างมาก ภาพนั้นแทบไม่ผิดเพี้ยน scale=iw+mod(iw,2):ih+mod(ih,2):flags=neighborหากคุณกำลังกังวลเกี่ยวกับความเร็วการกรองการใช้งาน สิ่งนี้สามารถเพิ่มแต่ละมิติได้เพียง 1 ถ้าจำเป็นและจะทำซ้ำแถว / คอลัมน์สุดท้าย
Gyan

@ Gyan นานเกินไปแล้วเพราะฉันมีปัญหาที่แก้ไขได้ (คำตอบของฉันถูกดึงออกมาจากความคิดเห็นที่ฉันทำไว้เมื่อนานมาแล้ว) แต่ฉันจำได้ว่าการปรับขนาดด้วยพิกเซลเดียวได้แนะนำสิ่งประดิษฐ์ที่มองเห็นได้ภายใต้เงื่อนไขบางประการ ในที่แรก. ฉันจำไม่ได้หรอกว่าอาจจะมีความพร่ามัวจากการเปลี่ยนแปลงพิกเซลเพียงครั้งเดียวหรือไม่? บางทีในรูปแบบ vid / image เท่านั้น? ทั้งหมดที่ฉันสามารถพูดได้ก็คือฉันได้ประมวลผล vids หลายพันรายการด้วยการแก้ไขนี้และเป็นการแปลงที่น่าพอใจ
danneu

19

อาจเป็นเพราะความจริงที่ว่าวิดีโอ H264 มักจะถูกแปลงจากพื้นที่ RGB เป็น YUV เป็น 4: 2: 0 ก่อนที่จะใช้การบีบอัด (แม้ว่าการแปลงรูปแบบเองนั้นเป็นอัลกอริทึมการบีบอัดแบบ lossy ทำให้ประหยัดพื้นที่ 50%)

YUV-420 เริ่มต้นด้วยรูปภาพ RGB (สีแดงสีเขียวสีน้ำเงิน) และแปลงเป็น YUV (โดยทั่วไปจะมีหนึ่งช่องสัญญาณความเข้มและสองช่อง "สี") จากนั้นช่องทางเว้จะถูกย่อยโดยการสร้างหนึ่งตัวอย่างเว้สำหรับทุก 2X2 ของสี่เหลี่ยมนั้น

หากคุณมีจำนวนพิกเซล RGB แปลกทั้งแนวนอนและแนวตั้งคุณจะมีข้อมูลที่ไม่สมบูรณ์สำหรับคอลัมน์พิกเซลหรือแถวสุดท้ายในพื้นที่ฮิวย่อยของกรอบ YUV


2
ข้อเท็จจริงที่น่าสนใจอีกข้อหนึ่ง ... เมื่อคุณถอดรหัสกับ Microsoft Media Foundation คุณจำเป็นต้องใช้ทวีคูณ 16 สำหรับ H264 วิดีโอ 1080P จึงถอดรหัสเป็นบัฟเฟอร์ที่สูงถึง 1,088 (แม้ว่าคุณจะไม่สนใจ 8 บรรทัดสุดท้าย)
Adisak

2

LordNeckbeard มีคำตอบที่ถูกต้องรวดเร็วมาก

-vf scale=1280:-2

สำหรับ Android อย่าลืมเพิ่ม

"-preset ultrafast" and|or "-threads n"

คุณไม่จำเป็นต้องประกาศหัวข้อ: ที่จัดการโดยอัตโนมัติ ผมเชื่อว่าช้า Andriod เมื่อการเข้ารหัสเพื่อ H.264 เป็นเพราะคนที่ใช้เป็นที่นิยม "WritingMinds / ffmpeg-หุ่นยนต์" ซึ่งใช้--disable-asmในของx264 สร้างสคริปต์ สิ่งนี้ส่งผลให้เกิดความล่าช้าที่ไม่จำเป็นและมีนัยสำคัญ (คุณสามารถตรวจสอบบันทึก ffmpeg และถ้ามันแสดงให้เห็นusing cpu capabilties: none!ว่ามันไม่ดี) ฉันไม่แน่ใจว่าทำไมพวกเขาเพิ่มสิ่งนั้น แต่ฉันไม่ใช่นักพัฒนา Android
llogan

1

คุณสามารถใช้bitandฟังก์ชั่นแทนtrunc:

bitand (x, 65534)

จะทำเช่นเดียวกับtrunc(x/2)*2และมันจะโปร่งใสมากขึ้นในความคิดของฉัน
(ลองพิจารณา65534ตัวเลขมหัศจรรย์ที่นี่;)


งานของฉันคือปรับขนาดโดยอัตโนมัติไฟล์วิดีโอให้มีความละเอียดเพียงครึ่งเดียว

scale=-2,ih/2 นำไปสู่การเล็กน้อย ภาพเบลอ

เหตุผล:

  • วิดีโออินพุตมีอัตราส่วนการแสดงผล (DAR)ตั้งค่า
  • scale ปรับขนาดของเฟรมที่แท้จริง
  • ในระหว่างการดูตัวอย่างขนาดของวิดีโอใหม่จะต้องได้รับการแก้ไขโดยใช้DARซึ่งในกรณีที่วิดีโอมีความละเอียดต่ำ(360x288, DAR 16: 9)อาจทำให้เกิดการเบลอ

สารละลาย:

-vf "scale='bitand(oh*dar, 65534)':'bitand(ih/2, 65534)', setsar=1"

คำอธิบาย:

  • output_height = input_height / 2
  • output_width = output_height * original_display_aspect_ratio
  • ทั้งoutput_widthและoutput_heightจะถูกปัดเศษให้เป็นจำนวนที่เล็กกว่าที่หารด้วย 2
  • setsar=1หมายถึงoutput_dimensionsเป็นที่สิ้นสุดไม่ควรใช้การแก้ไขอัตราส่วนกว้างยาว

บางคนอาจพบว่ามีประโยชน์

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