همون طور که میدونید ffmpeg یکی از کتابخانه های پر استفاده در مدیریت و پخش فایلهای تصویری و صوتی است. ابزارهای گرافیکی مختلفی برای کار با ffmpeg درست شدن، ولی کار با خط فرمان یک چیز دیگه است!
در این مطلب میخوام چند تا از کارهایی که من با ffmpeg لازم داشتم انجام بدم رو بنویسم.
ffmpeg -i input.mp4 -vcodec copy -acodec copy -ss 00:00:10 -to 00:09:05 output.mp4
دستور بالا میگه از ثانیه ۱۰ تا دقیقه ۰۹ و ثانیه ۰۵ کات کن و در یک فایل ذخیره کن. این کار رو هم بدون re-encode کردن ویدیو انجام بده. اگه ویدیوی شما حاوی keyframe باشه (یعنی فریم هایی که موقع ساخت ویدیو بعنوان نقطه عطف تعیین شدن! نمیدونم چطوری توضیح بدم!) موقع کات کردن بدون re-encode زمانی رو که شما تعیین کردید برش انجام بشه رعایت نمیشه و برش از نزدیک ترین keyframe اتفاق می افته. بنابراین دقیق نخواهد بود. ولی اگر ویدیو شما keyframe نداشته باشه، این مشکل پیش نمیاد.
ffmpeg -i input.mp4 -ss 00:00:10 -to 00:09:05 -async 1 output.mp4
دستور بالا هم برای کات کردن ویدیو هست. ولی با re-encode. این بار اگه ویدیو keyframe داشته باشه، اول ویدیو رو یک باره دیگه تولید میکنه و keyframe ها رو حذف میکنه و بعد اون رو کات میکنه. این طولانی تر خواهد بود ولی زمان برش دقیقا همان چیزی خواهد بود که شما تعیین کردید. ولی اگر میخواید چند تکه از یک ویدیوی حاوی keyframe رو کات کنید، نیاز نیست هربار re-encode کنید. با دستور زیر یک بار ویدیوی بدون keyframe تحویل بگیرید و عملیات برش رو روی این ویدیو با دستور اولی انجام بدید تا سریع برش ها انجام بشن:
ffmpeg -i input.mp4 -async 1 output.mp4
اگه ویدیویی دارید که با زاویه نادرست گرفته شده، میتونید اون رو با این دستور بچرخونید! من هر چی گشتم راهی پیدا نکردم که این کار رو بدون re-encode انجام بده. دستور زیر ویدیو رو با کدک libx264 یک بار re-encode میکنه و بعد میچرخونه. با اینکار کیفیت ویدیو دستخوش تغییر میشه.
ffmpeg -i input.mp4 -vf "transpose=1" -c:v libx264 -preset slow -crf 22 -c:a copy output.mp4
مقداری که برای transpose میدیم مشخص میکنه ویدیو به چه زاویه ای بچرخه:
-vf "transpose=2,transpose=2"
فرض کنید میخوایم یک ویدیو رو کراپ کنیم. اول تست کنیم ببینیم اندازه ای که میخوایم چیه و چجوری قراره در بیاد. برای اینکه اندازه های ویدیو دستتون بیاد، اول با دستور زیر اندازه های ویدیوی مورد نظر رو پیدا کنید:
ffprobe -v error -select_streams v -show_entries stream=width,height -of csv=p=0:s=x input.mp4
مثلا میگه 1200x800 و ما میخوایم مقداری از این ویدیو رو کراپ کنیم! منتها اول باید مطمئن بشیم که از جای درست داریم کراپ میکنیم. دستور زیر قبل از اینکه فایل خروجی رو ذخیره کنه، پیش نمایش کراپ شده رو نشون میده. بنابراین میتونیم با تغییر اندازه ها، محل مورد نظرمون رو پیدا کنیم:
ffplay -i input.mp4 -vf "crop=480:400:0:0"
معنی دستور بالا یعنی به پهنای ۴۸۰ و ارتفاع ۴۰۰ از گوشه چپ ویدیو به پهنای 0 و ارتفاع 0 تصویر رو کراپ کن. با بازی با این عددها دستتون میاد که کجای ویدیو رو چجوری پیدا کنید! راستش راه راحت تری پیدا نکردم!
حالا با دستور زیر وقتی اندازه مورد نظرمون رو پیدا کردیم، ویدیوی کراپ شده رو ذخیره میکنیم. البته با re-encode کردن با libx264 که شما میتونید هر جوری که دلتون میخواد ویدیو رو انکود کنید. در این زمینه به مستندات ffmpeg مراجعه کنید. (انواع کدک ها و میزان کیفیت و ...)
ffmpeg -i input.mp4 -vf "crop=480:400:0:0" -c:v libx264 -crf 22 -c:a copy output.mp4
با استفاده از دستور زیر، یک واترمارک (تصویر) به محل دلخواهی از ویدیو اضافه میشه. در این مثال در گوشه چپ و بالای تصویر
ffmpeg -i video.mp4 -i image.png -filter_complex "overlay=15:10" -preset veryfast output.mp4
دستور زیر صدا رو از ویدیو بر میداره و یک فایل ویدیویی بدون صدا تحویل میده
ffmpeg -i input.mp4 -c copy -an output.mp4
اگه بخواید یک فایل زیرنویس رو به ویدیو اضافه کنید، طوری که بشه از توی پخشکننده انتخاب کرد که زیرنویس نشون داده بشه یا نه:
ffmpeg -i input.mp4 -f srt -i subtitle.srt -c:v copy -c:a copy -c:s mov_text -metadata:s:s:0 language=per output.mp4
با -metadata
میگیم که این زیرنویس زبانش چی هست. مثلا ما گفتیم per
یعنی persian
توجه: برای فایلهای .mkv
بجای -c:s mov_text
از -c:s srt
استفاده کنید.
و اگر بخواید زیرنویس رو روی فیلم بچسبونید یا اصطلاحلا burn کنید تا همیشه نشون داده بشه و حق انتخاب برای عدم نمایش نداشته باشه:
ffmpeg -i input.mp4 -vf subtitles=subtitles.srt output.mp4
برای اینکه چند زیرنویس (مثلا یکی فارسی و یکی انگلیسی) رو به ویدیو اضافه کنیم، به طوری که در مدیاپلیر بتونیم انتخاب کنیم کدوم زیر نویس نشون داده بشه، باید از -map
استفاده کنیم. یک نمونه اینجا میذارم:
ffmpeg -i input.mp4 -f srt -i sub1.srt -i sub2.srt -map 0:0 -map 0:1 -map 1:0 -map 2:0 -c:v copy -c:a copy -c:s mov_text -metadata:s:s:0 language=per -metadata:s:s:1 language=eng output.mp4
در مثال بالا، فایل اولی یعنی sub1.srt زیرنویس فارسی و فایل دومی یعنی sub2.srt زیرنویس انگلیسی است. با -metadata
هم مشخص میکنیم کدومشون کدومه!
توجه: برای فایلهای .mkv
بجای -c:s mov_text
از -c:s srt
استفاده کنید.
حاصل سر و کله زدن های من با لینوکس