Computer >> บทช่วยสอนคอมพิวเตอร์ >  >> ซอฟต์แวร์ >> ซอฟต์แวร์

Master ffmpeg: คู่มือ Multimedia Editing ครบวงจร

ผ่านหลายปี มาแล้ว หลายโอกาสที่ผมต้องทำ Multimedia Editing บางรูปแบบ Audio, Video อะไรก็ตาม ไม่ว่าจะเป็นการสร้างคลิปไม่ขำขันสำหรับ Youtube Channel, Extract หรือ Convert เพลง, ฝัง Subtitles ซ้ำๆ ผมพบว่าตัวเองใช้ ffmpeg บน Command-line และเพลิดเพลินกับกระบวนการตลอด พร้อมตกอยู่ในความประหลาดใจที่ละเอียดอ่อนต่อความสามารถของโปรแกรมที่ไม่เอาแต่นี้

ผมคิดว่า ควรเขียนคู่มือ ffmpeg ที่ครอบคลุมมากขึ้น หนึ่งที่รายการ Tasks และ Functions หลากหลาย และ Wrap รอบตัวอย่าง Real-life และ Use Cases แม้ผมจะกล่าวถึง ffmpeg ครั้งแรกใน Tutorial แก้ไข Flash ปี 2008 แต่นี้คือ Article ใหม่ Fresh และ Up-to-date จะเป็น Command-line จะเป็น Nerdy แต่ควรจะสนุกด้วย ติดตามมา

พื้นฐาน (Basics)

Ffmpeg มีใน Linux Distribution ทุกตัวเกือบหมด และมี Builds สำหรับ Windows และ Mac หากอยากรู้มันทำอะไรได้ ตรวจสอบความสามารถโดยรัน ffmpeg โดยไม่มี Arguments หรือกับ Flag -hide_banner ทางเลือก ใช้ Help Option สำหรับโปรแกรมหลักและ Sub-commands มากมาย Features อาจ Intimidating ดังนั้นเราจะดำเนินการช้าแต่แน่นอน อย่าลืม Documentation จริงๆ มันค่อนข้าง Neat

การแปลงและ Transcoding (Conversion and Transcoding)

งานทั่วไปที่สุดคือแปลงไฟล์จากรูปแบบหนึ่งไปอีกรูปแบบ จดจำตัวอย่าง Extract Audio จาก FLIP Clip? เหมือนกัน แต่อาจอยากแปลงวิดีโอจากกล้องเป็น MP4 หรือ Convert OGG เป็น MP3 หรือคล้ายๆ กัน มี Scenarios ไม่มีที่สิ้นสุด และ Modes และ Formats ที่รองรับใน ffmpeg ไม่มีที่สิ้นสุดเช่นกัน ปกติคุณจะทำ:

  • ระบุ Input File
  • ระบุ Video และ Audio Codecs ที่ต้องการ
  • ระบุ Output File

ถ้าไม่ต้องการ Manipulate Video Stream ใช้ Codec Copy เดียวกันกับ Audio ใช้ Option นี้ถ้าอยากเปลี่ยน Container เช่น จาก MOV เป็น MP4 โดยไม่เปลี่ยน Encoding จริง

ffmpeg -i MVI_1348.MOV -c:v copy -c:a copy new.mp4

หมายเหตุ: ไม่ใช่ทุก Format รองรับ Codecs และ Options ทั้งหมด ดังนั้นอาจไม่ทำงานในบางกรณี เช่น:

[mp4 @ 0x55a21519fb20] Could not find tag for codec vp8 in stream #0, codec not currently supported in container
Could not write header for output file #0 (incorrect codec parameters ?): Invalid argument
Stream mapping:
Stream #0:0 -> #0:0 (copy)
Stream #0:1 -> #0:1 (copy)
Last message repeated 1 time

ถ้าต้องการ Extract Stream เฉพาะ - Audio, Video, Subtitles หรือ Data - สามารถ Suppress การประมวลผล Stream อื่นๆ (เพื่อประหยัดเวลาและ CPU Cycles) ตัวอย่าง ถ้าต้องการแค่ Audio จากไฟล์ Audio-Video รวม ใช้ Option -vn (No Video)

ffmpeg -i MVI_1348.MOV -vn -ar 44100 -ab 192k sound-only.mp3

Utility อัศจรร่ายนี้ให้ Flexibility มากในวิธีการทำสิ่งต่างๆ เช่น codec:v, vcodec และ c:v เหมือนกันหมด ใช้ตัวไหนก็ได้ ถ้าต้องการแค่ Audio Output เหมือนข้างบน ffmpeg จะ Guess และ Assume ว่าคุณหมายถึง -vn ด้วย สามารถใช้ Flag -f บังคับ Output Format ได้ แต่ Tool จะพยายาม Guess ผลลัพธ์จาก Command ของคุณ ตัวอย่าง ใช้ -f mp3 หรือ acodec mp3

Codecs ต่างๆ จะมี Options ต่างกัน เช่น Audio File อาจระบุ Audio Sampling Rate และ Audio Bitrate, จำนวน Channels และอื่นๆ ถ้าข้ามบาง Options Command อาจ Fail หรือใช้ Defaults

Scale และ Quality (Scale and Quality)

งานทั่วไปอีกอย่างคือเปลี่ยนขนาดวิดีโอ (Resolution) และ Quality ของ Streams Ffmpeg ทำได้หลายวิธี Force Ratio (และทำลาย Aspect Ratio เริ่มต้น) หรือ Preserve โดยระบุ Vertical หรือ Horizontal Value บวก Magic Qualifier สามารถ Crop Video Borders และ Re-encode Streams ต้องการตัวอย่างในขั้นนี้

ffmpeg -i input.avi -c:v mpeg4 -vtag xvid -qscale:v 3 -c:a libmp3lame -qscale:a 4 output.avi

อะไรอยู่ที่นี่? เรา Transcode AVI Input ด้วย MPEG4 Video Stream Quality 3 (qscale) สำหรับ Codecs บางตัว Quality 1-31 โดย 1 สูงสุด ผมทดสอบบน Input Files ทั่วไป Quality สูงสุดปกติให้ขนาด Double ขณะ 3 หรือ 4 ให้ Reduction ประมาณ 20-30% Vtag xvid เป็น Option เฉพาะ MPEG-4 Audio ใช้ LAME

ffmpeg -i MVI_1348.MOV -vfilters scale=1280:-1 -c:a copy scaled.mp4

ตัวอย่างนี้แสดง Video Scaling (ใช้ -vf หรือ -vfilters) Aspect Ratio ถูก Preserve ผ่าน -1 Qualifier ไม่เปลี่ยน Quality Stream Audio Stream ถูก Copy เข้า Output Container ถ้า Original Video Resolution สูงกว่าที่ระบุ จะ Downscale ถ้าต่ำกว่า Upscale

Image Extraction, Combination, GIFs

Ffmpeg จัดการรูปภาพได้ แม้จะเป็น Media Utility แต่รูปภาพก็คือ Media และ Video คือ Moving Pictures ทุกอย่าง! งานที่อยากทำ - Extract Frames จาก Video สร้าง Thumbnails (คุณภาพสูง) แทนที่จะ Pause Video แบบ Manual หรือ Screenshots วุ่นวาย สร้าง Stopmotion Video จาก Stills - หรือ Full Video แปลง Video เป็น Animated GIFs สำหรับ Dank Memeism บน Web อีกครั้ง สาธิตด้วยตัวอย่าง... Dank

ffmpeg -i input.mp4 -r 1 -f image2 thumb-%3d.png

ระบุ Input File, Rate (1 Image ต่อ 1 วินาทีของ Video), Format (image2), Output Format ทำอย่างฉลาด ถ้าเคยเห็น C Code จะคุ้นเคย ต้องการ Numbering Sequence สำหรับ Thumbnails ให้มี 3 Digits เลือก Digits จำนวนไหนก็ได้ แต่ควรมากกว่าจำนวนรูปที่คาดว่าจะ Extract

Master ffmpeg: คู่มือ Multimedia Editing ครบวงจร

การรวม Images เป็น Video คล้ายกัน:

ffmpeg -f image2 -i thumb-%3d.png stopmotion.mp4

ระบุ Rate ได้ (อยากให้ Video เป็น 24 หรือ 30 FPS) จะพูดถึงเพิ่มเติมตอนพูดถึงการทำ Video Playback ช้าหรือเร็ว และเพราะพูดถึง Images Resize ได้:

ffmpeg -i thumb-004.png -vf scale=400:-1 test.png

Animated GIFs น่าสนใจ และ Simple มาก แค่ระบุ Input File และตั้ง Output ให้มี Extension .gif Ffmpeg จะ Auto-guess ส่วนที่เหลือ และสร้าง Animated GIF คุณภาพสูงสวยงาม

ffmpeg -i MVI_6654.MOV test.gif

Master ffmpeg: คู่มือ Multimedia Editing ครบวงจร

สุดท้าย ตรงข้ามของ GIFs อาจอยากได้ Video ประกอบด้วย Single Image - Constant Preview แต่มี Music หรือ Podcast เล่นใน Background Ffmpeg ทำได้ด้วย Trick ฉลาด

ffmpeg -loop 1 -i thumb-001.png -i sound-only.mp3 -c:v libx264 -shortest video-static-image.mp4

ให้ 2 Inputs โดยแรกเป็น Image Set Loop เรา Re-encode Video แต่เพราะ Image Loop ตลอดกาล ต้องการ Option Shortest เพื่อจบ Operation เมื่อ Clip สั้นที่สุดจบ ซึ่งคือ Video ในกรณีนี้

Splitting และ Joining Videos

Scenario ที่มีประโยชน์อีกอย่าง ถ้ามี Clip ใหญ่มาก แต่ต้องการแค่ไม่กี่นาทีหรือวินาที ffmpeg ตัดชิ้นที่ต้องการได้ รวมหลายไฟล์เป็น Stream เดียว - ทั้ง Video และ Audio ffmpeg ให้เลือก Start และ End Timestamps ที่ต้องการ Leeway มากในการจัดการ

-t duration         Record หรือ Transcode "duration" วินาทีของ Audio/Video
-to time_stop       Record หรือ Transcode Stop Time
-fs limit_size      Set Limit File Size ใน Bytes
-ss time_off        Set Start Time Offset
-sseof time_off     Set Start Time Offset Relative to EOF
-seek_timestamp     Enable/Disable Seeking by Timestamp กับ -ss
-timestamp time     Set Recording Timestamp ('now' เพื่อ Set
                    Current Time)

ลองแบบนี้:

ffmpeg -i MVI_1348.MOV -ss 4 -t 4 spliced.mp4

Command นี้ Extract 4 วินาทีจาก Input Clip เริ่มที่ Time Offset 4 วินาที เข้าไปใน Clip ใช้ Short Notation (4 แสดงวินาที) หรือ Full hh:mm:ss.mmm ให้ Accuracy ลงมิลลิวินาที พอสำหรับ Use Cases ทั้งหมด

Joining Files ซับซ้อนกว่า ทางเทคนิคเรียกว่า Concatenation (Concat) ทำงานต่างจาก Cutting ไม่ระบุ Parts ที่ต้องการ Join บน Command Line ใส่ในไฟล์ด้วย Notation เฉพาะ แล้วอ่านไฟล์นั้นด้วย ffmpeg ตัวอย่าง:

ffmpeg -f concat -i list.txt -codec copy joined.mp4

เนื้อหา list.txt จะเป็น:

file 'part-1.mp4'
file 'part-2.mp4'
file 'part-3.mp4'

จดจำการใช้คำว่า file และ Single Quotation Marks ใช้ Absolute และ Relative Paths ได้ ถ้าทำผิด Format ไฟล์ จะเห็น Error:

[concat @ 0x555ca89c38c0] Line 1: unknown keyword 'part-1.mp4'
list.txt: Invalid data found when processing input

ถ้าพยายามให้ List of Files บน Command Line (แทน Text File):

part-1.mp4: Invalid data found when processing input

ฝังและแยก Subtitles (Embed and Extract Subtitles)

จำบทความ VLC & Subtitles ของผมไหม? ถ้าไม่ Intimidated โดย Command Line ทำอย่างเดียวกันกับ ffmpeg ได้ ตัวอย่าง Trivial สมมติมี Audio และ Subtitle Files แยกกัน โดยไม่ต้อง Processing เพิ่ม ใช้ Video Filtering Option:

ffmpeg -i input.avi -vf subtitles=subtitle.srt output.avi

Use Case ซับซ้อนกว่า Command ด้านล่าง จะรับ MP4 และ Subtitle Files แยกกัน รวมเป็น Output File พร้อม Video Transcoding Option -map (แสดง 2 ครั้ง ไม่ใช่ Error) กำหนดลำดับ Streams จะ Map เข้า Output แต่มี Codec Listing ที่ฉลาดและ Confusing เล็กน้อย เพราะมี Multiple Streams เราอยาก Manipulate แค่ Video Part - ไม่ใช่ Audio หรือ Subtitles

เพื่อนั้น -c copy ระบุว่า Copy All Codecs แต่ -c:v Override Option นี้ และ Video Stream จะ Transcode ใช้ libx264 Codec ดังนั้นใช้ Constant Rate Factor (CRF) สำหรับ Variable Bitrate ตั้ง 23 (Range Lossless 0 ถึง Lowest-quality 51) และ Veryfast Preset สร้าง Output ค่อนข้างเล็ก

ffmpeg -i input.mp4 -i subtitle.srt -map 0 -map 1 -c copy -c:v libx264 -crf 23 -preset veryfast output.mp4

Extract Subtitles เป็นแบบนี้:

ffmpeg -txt_format text -i input.file out.srt

เร่งและช้าวิดีโอ (Speed up and Slow Videos)

Use Case น่าสนใจอีกอย่าง เหมือนมนุษย์ทั่วไป อาจอยากเอา Video เร็ว 2x แล้วเพิ่มเพลง Benny Hill และควรมีความสุขมาก คุณอาจช้าลง Action และเพิ่ม Smoothing เพื่อ Sequence ที่ช้าไม่รู้สึก Stilted

ตัวอย่าง เราอาจมี Stop Motion Video - มีแค่ 15-20 Thumbnails ใช้เวลา 1 วินาทีเล่น จะอยาก Stretch ให้ 5 วินาที แต่อาจหมายถึงแต่ละ Frame แสดงนาน 5 เท่า แทนที่จะ Insert Extra Frames ทำให้ดู Smooth Slo-mo เราทำด้วย AviSynth และ VirtualDub ตอนนั้น

Video Speed Filter ทำงานโดยเปลี่ยน Presentation Timestamp (PTS) ของแต่ละ Video Frame 簡單地说 Fractional Values เร่ง Video Multipliers > 1 ช้า เมื่อเร่ง Ffmpeg จะ Drop Frames แต่ระบุ Framerate สูงกว่าได้ เพื่อ Preserve Original คูณ FPS ใน Input ด้วย 1/PTS ที่ใช้ ถ้า Double Speed ของ 24FPS Clip ควรใช้ 48FPS Rate

ffmpeg -i input.mp4 -filter:v "setpts=0.5*PTS" output.mp4

ffmpeg -i input.mp4 -r 96 -filter:v "setpts=0.25*PTS" output.mp4

ffmpeg -i input.mp4 -filter:v "setpts=2*PTS" output.mp4

Smoothing Videos ซับซ้อนกว่า ผมต้อง Consult Documentation โดยพื้นฐาน สำหรับ Video ที่ช้า 5 เท่า (และยาว 5 เท่าของต้นฉบับ) ใช้ Video Interpolation สร้าง Smoothing Effect ที่นี่ก็ต้อง Add FPS เพื่อให้ Ffmpeg มี Data พอ Guess Frames ระหว่างกัน ในตัวอย่าง 5x Slowed Down ต้อง 5x24 FPS (Original Speed) Ergo 120 FPS

ffmpeg -i input.mp4 -filter:v "minterpolate='mi_mode=mci:mc_mode=aobmc:vsbmc=1:fps=120'" output.mp4

Task นี้ CPU-intensive และใช้เวลานาน ผมใช้ ffplay Preview Videos ผลลัพธ์ Reasonable แต่อาจไม่ Magic Something from Nothing ดังนั้นทำงานดีเมื่อ Data ขาดน้อย (ไม่ใช่ 1 Frame ต่อ 2 วินาที หรือแบบนั้น)

สำหรับ Audio ใช้ Atempo Option Range 0.5-2.0 หมายถึงครึ่งหรือคูณ 2 สูงสุด แต่ Chain Multiple Atempo Filters ได้เพื่อ Speed Changes เพิ่มเติม เช่น ตัวอย่างด้านล่าง:

ffmpeg -i input.mp4 -filter:a "atempo=2.0,atempo=2.0" -vn output.mp4

และนี่จบ Tutorial นี้

สรุป

หวังว่าคุณจะพบว่ามัน Fruitful, Enjoyable และ Relevant Ffmpeg คือ Workhorse - ไม่ มันคือ Cavalry ทั้งหมด - ของ Audio และ Video Tweaking ใน Linux และมี Practical Tools, Options และ Configurations มากมาย การเริ่มต้นอาจ Confusing และ Intimidating อารมณ์เหล่านี้ควรหายไปแล้วตอนที่คุณอ่าน Tutorial นี้จบ

เราพูดถึง Conversion และ Transcoding, Scaling และ Quality, Image Extraction, Combination และ GIF Creation, Splitting และ Joining Videos, Subtitle Extraction และ Embedding, Video Speedup และ Slowdown และอื่นๆ อีกเยอะ นี่ควรทำให้คุณมีความสุขและยุ่งมานาน หากมี Requests หรือ Questions เรื่อง ffmpeg ยิงมาได้ Email เพียงคลิกเดียว หรืออย่างนั้น สุดท้าย ถ้า Tutorial นี้ Useful จริง ให้ Love กลับบ้าง เพราะทำไมไม่

ขอให้สนุกกับการทำงาน!