วิธีการเข้ารหัสลำดับภาพ jpg กับวิดีโอใน ffmpeg โดยไม่สูญเสียข้อมูล


21

ฉันมีชุด jpgs จำนวนมากที่ฉันต้องการแปลงเป็นวิดีโอที่ไม่สูญเสีย (หรืออย่างน้อยที่สุดก็ใกล้เคียงกับ lossless ตราบใดที่เวลาการเข้ารหัสไม่สูงกว่าอย่างอื่นมาก)

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

มีตัวแปลงสัญญาณและการตั้งค่าที่เหมาะสมสำหรับ ffmpeg ที่สามารถทำสิ่งนี้ได้หรือไม่?



ยังมีความเกี่ยวข้อง: avp.stackexchange.com/questions/7300/…
เพื่อนของจอร์จ

1
ลำดับของ jpegs เป็นตัวแปลงสัญญาณเป็นเวลานาน กล้องดิจิตัลที่ไม่ใช้ h.264 บันทึก MJPEG อย่างสม่ำเสมอและการ์ดจับภาพวิดีโอที่ใช้งานฉันคิดว่า
Peter Cordes

คำตอบ:


24

เพียงแค่ผสมภาพ

คุณสามารถผสมภาพ JPG เพื่อสร้างวิดีโอได้ง่ายๆ:

ffmpeg -framerate 30 -i input%03d.jpg -codec copy output.mkv

โปรดทราบว่าหากคุณไม่ใช้-framerateจะใช้ค่าเริ่มต้นของ-framerate 25อินพุต

การเพิ่มประสิทธิภาพแบบไม่สูญเสีย

คุณสามารถใช้jpegtranเพื่อเพิ่มประสิทธิภาพการสูญเสียในแต่ละเฟรมซึ่งอาจให้การประหยัดขนาดไฟล์ที่สำคัญ

mkdir outputdir
for f in *.jpg; do jpegtran -optimize -copy none -perfect -v "$f" > "outputdir/$f"; done

ตอนนี้ mux พร้อมffmpegดังที่แสดงด้านบน

ตรวจสอบว่าเป็น lossless จริง

Muxer framehashสามารถนำมาใช้เพื่อเปรียบเทียบกัญชาที่เป็นเอกลักษณ์ของแต่ละเฟรมเพื่อให้มั่นใจว่าผลที่ได้คือ lossless อย่างแท้จริง:

$ ffmpeg -i input%03d.jpg -f framehash -
stream_index, packet_dts, packet_pts, packet_duration, packet_size, hash
0,          0,          0,        1,   460800, 29bcc2db3726c7dfec1826c5740f603f
0,          1,          1,        1,   460800, b5fdc23d93cbd043dc2b9290dc8378f0
0,          2,          2,        1,   460800, ee0709942f24b458fd2380d134dcb59d
...

$ ffmpeg -i output.mkv -map 0:v -f framehash -
stream_index, packet_dts, packet_pts, packet_duration, packet_size, hash
0,          0,          0,        1,   460800, 29bcc2db3726c7dfec1826c5740f603f
0,          1,          1,        1,   460800, b5fdc23d93cbd043dc2b9290dc8378f0
0,          2,          2,        1,   460800, ee0709942f24b458fd2380d134dcb59d
...

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

ยังดู


คุณช่วยอธิบายให้ชัดเจนว่าframemd5คำสั่งทั้งสองนั้นควรทำอะไรได้มากกว่าเพียงแค่การระบุรายการแฮช ฉันจะได้รับการบีบอัดเพิ่มเติมอย่างไรเมื่อระบุเฟรมที่เหมือนกัน
GJ

1
แฮชถูกรวมไว้เพื่อแสดงให้คุณเห็นว่าเฟรมเหมือนกันกับภาพแต่ละภาพดังนั้นจึงบรรลุความต้องการของคุณในการจัดเก็บ "เฟรม jpg แต่ละเฟรมตามที่เป็นอยู่ (โดยไม่มีการบีบอัดซ้ำ)"
llogan

โพสต์คำตอบของฉันเองด้วยความคิดที่ยังไม่ทดลองสำหรับการวางเฟรมที่ซ้ำกันเพื่อท้ายด้วย VFR MJPEG.mkv VFR เป็นวิธีเดียวที่ฉันสามารถคิดที่จะใช้ประโยชน์จากความซ้ำซ้อนทางโลกกับ MJPEG : P
Peter Cordes

SSIM อาจเป็นวิธีที่รวดเร็วกว่าในการเปรียบเทียบความเที่ยงตรง
Gyan

11

สิ่งนี้จะแสดงผลวิดีโอ H.264 แบบไม่สูญเสียที่เฟรมจะใช้ข้อมูลจากเฟรมอื่น

ffmpeg -f image2 -r 30 -i %09d.jpg -vcodec libx264 -profile:v high444 -refs 16 -crf 0 -preset ultrafast a.mp4

คำอธิบายของตัวเลือก:

  • -f image2 - บอก ffmpeg ให้เลือกกลุ่มของภาพ
  • -r 30 - บอกให้ ffmpeg เข้ารหัสที่ 30 เฟรม (หรือภาพ) ต่อวินาที (เปลี่ยนเป็น framerate ที่คุณต้องการ)
  • -i %09d.jpg- บอกให้ ffmpeg ใช้ภาพ 000000000.jpg ถึง 999999999.jpg เป็นอินพุต เปลี่ยน9ใน%09d.jpgการ zeroes วิธีการหลายชื่อลำดับภาพของคุณได้ ตัวอย่างเช่นหากชื่อไฟล์ของคุณคือ img0001.jpg ข้อมูลนี้จะแสดงเป็น img% 04d.jpg
  • -vcodec libx264 - บอก ffmpeg เพื่อส่งออกไปยังไฟล์ที่สอดคล้องกับ H.264
  • -profile:v high444 - บอกให้ libx264 ใช้โปรไฟล์ High Loss Loss Predictive High 4: 4: 4 ซึ่งอนุญาตการเข้ารหัสแบบไม่สูญเสียข้อมูล
  • -refs 16 - บอกให้ libx264 เก็บภาพไว้ในบัฟเฟอร์ 16 ภาพเพื่อให้สามารถอ้างอิงรูปภาพอื่น ๆ ในวิดีโอได้
  • -crf 0 - บอกให้ libx264 ทำการเข้ารหัสแบบไม่สูญเสียข้อมูล
  • -preset ultrafast - บอกให้ libx264 จัดลำดับความสำคัญความเร็วการเข้ารหัสเหนือขนาดไฟล์ที่ส่งออก
  • a.mp4- บอก ffmpeg ให้บันทึกผลลัพธ์ในไฟล์ MP4 ชื่อ a.mp4 เปลี่ยนเป็นชื่อไฟล์และรูปแบบที่คุณต้องการใช้

3
หมายเหตุเล็กน้อย: -f image2ไม่จำเป็นที่นี่ demuxer ไฟล์ภาพควรใช้แทน-framerate -rlibx264 โดยอัตโนมัติจะเลือกที่เหมาะสม-profileสำหรับ lossless และจะจัดการกับ-preset -refs
23470 llogan

-refs 5ที่ MOST ยกเว้นว่าคุณรู้ว่าเนื้อหาของคุณมีภาพที่เหมือนกันคั่นด้วยภาพอื่น ๆ อีกหลายภาพซึ่งอาจทำให้ x264 สูญเสียการอ้างอิงก่อนที่จะซ้ำซ้อน สูงกว่าultrafastทำให้แตกต่างกันเล็กน้อยในโหมด lossless นอกเหนือจาก CABLC มากกว่า ~ 10% ได้รับมากกว่า CAVLC (สำหรับค่าซีพียูสูงที่ bitrates ที่จำเป็นสำหรับ lossless) อย่างจริงจังในบางไลฟ์แอ็กชัน 720x480p60 (เอาต์พุต deinterlace) superfastคือ 28GB slowerเป็น 27GB หากเวลาในการเข้ารหัสไม่สำคัญ แต่เวลาในการถอดรหัสตรวจสอบให้แน่ใจว่าคุณหลีกเลี่ยง CABAC -tune fastdecodeแม้อาจจะ จำนวนการอ้างอิงปานกลางไม่ควรเจ็บ
Peter Cordes

และถ้าคุณมีซีพียูที่จะเผาไหม้คุณสามารถลอง-preset placeboเศษส่วนพิเศษอีกสองสามเปอร์เซ็นต์
DrYak

นอกจากนี้เพื่อความสมบูรณ์ h265 ยังมีโหมด lossless ของตัวเอง -vcodec libx265 -x265-params lossless=1เป็นตัวเลือกที่เทียบเท่า (แต่จากประสบการณ์ของฉัน (= การบันทึกการนำเสนอสไลด์โชว์ Powerpoint) ไม่จำเป็นต้องดีกว่าและช้ากว่า h264 มาก) ปรับแต่งสำหรับ Daala AV1 / IETF ของ NETVC1 / Xiph ของ Daala ในปีหน้า โหมดการสูญเสียของ ...
DrYak

5

คุณสามารถสร้างaviภาพเคลื่อนไหวเป็นชุดของpngภาพ ( png เป็น lossless ดังนั้นjpeg => pngการแปลงไม่ควรลดภาพของคุณ):

หากภาพของคุณมีชื่อ img_0001.jpg

ffmpeg -r 25 -start_number 1 -f image2 -i "img_%04d.jpg" -vcodec png video.avi

โดยที่ "25" คืออัตราเฟรมที่คุณต้องการในวิดีโอผลลัพธ์ -start_numberไม่จำเป็นถ้าเป็น 1 แต่จะมีประโยชน์หากหมายเลขวิดีโอแรกของคุณไม่ใช่ 1

หากคุณต้องการเข้ารหัสmjpegด้วยบรรทัดคำสั่งที่มีคุณภาพสูงสุดคือ:

ffmpeg -r 25 -start_number 1 -f image2 -i "img_%04d.jpg" -vcodec mjpeg -qscale 1 video.avi

และความสวยงามของสิ่งต่าง ๆ ก็คือคุณสามารถแปลงวิดีโอกลับเป็นรูปภาพได้แบบ:

ffmpeg -i video.avi "img_series_%04d.png"
ffmpeg -i video.avi "img_series_%04d.jpg"

ฯลฯ ...


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

ที่จริงฉันคิดว่าเขายินดีที่จะบีบอัดบางอย่าง แต่ฉันไม่แน่ใจว่ามันจะทำอย่างไรกับลำดับที่ยาวนานของเฟรมเดียวกัน ฉันยังคิดว่ารูปแบบการนำเสนออัตราเฟรมที่เปลี่ยนแปลงเป็นสิ่งที่จำเป็น แต่ฉันไม่แน่ใจว่า ffmpeg รองรับหรือไม่
AJ Henderson

CorePNG สามารถสร้างเฟรม P ได้เช่นกัน โดยปกติแล้ว jpeg ไม่ใช่การบีบอัดแบบ lossless และฉันสงสัยว่า mjpeg สามารถสร้างเฟรม P ได้ ฉันเห็นด้วยฉันไม่ตอบคำถามตามที่ถาม แต่ฉันให้วิธีแก้ไขวิดีโอ lossless ด้วย ffmpeg
Olivier S

4

เพื่อขยายคำตอบของ LordNeckbeard ใช่เพียงแค่ mux ข้อมูล JPEG ลงในสตรีมวิดีโอ MJPEG นั่นจะเป็นการแสดงลำดับภาพที่เล็กที่สุดแม้ว่า MJPEG จะเป็นตัวแปลงสัญญาณที่ไม่มีประสิทธิภาพอย่างมากตามมาตรฐานในปัจจุบัน (ไม่มีความซ้ำซ้อนทางโลกและไม่มีแม้แต่คำทำนายภายใน

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

ffmpeg -framerate 30 -i input%03d.jpg -vf mpdecimate -codec copy output.mkv  # doesn't work.

อืมสิ่งนี้จะไม่ทำงานเนื่องจาก mpdecimate จะไม่ทำงานกับข้อมูลที่ถูกบีบอัดและเราไม่สามารถปล่อยให้ ffmpeg ถอดรหัสแล้วจึง jpeg ข้อมูลภาพอีกครั้งโดยไม่สูญเสียและต้นทุน CPU

บางทีถ้าคุณแทนที่ไฟล์ jpg ที่ซ้ำกันด้วยไฟล์เปล่าด้วยหมายเลขลำดับนั้นหรือบางอย่าง?

เนื่องจากคำถามนี้ไม่ได้ล่าสุดฉันจะไม่ใช้เวลาในการคิดออกว่าจะทำอย่างไรถ้ามีคนตอบถามว่า แต่เนื่องจาก MJPEG สามารถเข้าไปในคอนเทนเนอร์ mkv ได้ฉันมั่นใจว่าเป็นไปได้ที่จะมีไฟล์ที่ไม่ได้ทำซ้ำข้อมูล jpeg สำหรับเฟรมที่ทำซ้ำ แต่แทนที่จะไม่มีเฟรมเอาต์พุตที่จะถอดรหัสจนกว่าลำดับที่ซ้ำกันจะเป็น เกิน.

โอ้นี่เป็นความคิด:

ffmpeg -framerate blah -input blah -vf mpdecimate -f mkvtimestamp_v2 mpdecimate.timestamps

จากนั้นลบ (หรือย้ายออก) jpegs ทั้งหมดสำหรับเฟรมที่ mpdecimate ต้องการวาง (อาจมีตัวเลือกการบันทึกบางส่วนหรือ -vf showinfo และแยกวิเคราะห์และย้ายหรือ hardlink เฉพาะเฟรมที่แสดงในเอาต์พุตทิ้งไว้ข้างหลัง JPEG ที่หล่นหรือไม่) MUX ที่ไป MJPEG.mkv แล้วทำอะไรกับ mkvmerge เพื่อแทนที่ timestamps mpdecimate.timestampsกรอบในการที่มีการประทับเวลาจาก

ถ้าคุณได้ xcoding แทนเพียง muxing ข้อมูล JPEG เพื่อ MJPEG นี้จะง่ายมากเพราะคุณต้องการเพียงแค่ใช้คำสั่งแรกของฉันกับ mpdecimate และตัวแปลงสัญญาณใด ๆ อื่น ๆ กว่าcopyและมันก็จะทำงาน (TM)

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

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