Last active
January 12, 2023 09:33
-
-
Save gaborbata/23c3de70ba15c2e0d28c4fdbc3c9fadb to your computer and use it in GitHub Desktop.
Convenience methods for ffmpeg
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#!/usr/bin/env ruby | |
# Convenience methods for ffmpeg | |
# Character encoding of subtitle | |
SUB_ENCODING = 'ISO-8859-2' | |
# Subtitle language | |
SUB_LANG = 'hun' | |
# List of supported commands | |
COMMANDS = { | |
'embedsrt' => lambda do |args| embed_srt(args) end, | |
'normalize' => lambda do |args| normalize_audio end, | |
'extract_audio' => lambda do |args| extract_audio end, | |
'help' => lambda do |args| puts "supported commands: #{COMMANDS.keys.join(', ')}" end | |
} | |
# Embed srt subtitles into video files | |
def embed_srt(args) | |
encoding = args[0] || SUB_ENCODING | |
puts 'Subtitle encoding: ' + encoding | |
Dir.glob('*.{mp4,avi,mkv}').sort.each do |video_file| | |
ext = File.extname(video_file) | |
name = File.basename(video_file, ext) | |
if !File.exist?(name + '.srt') | |
puts "Skipping '#{name}' due to missing subtitle" | |
next | |
end | |
# remove previous subtitles | |
if ext == '.avi' | |
system("ffmpeg -fflags +genpts -i \"#{name}#{ext}\" -vcodec copy -acodec copy -sn \"#{name}_temp.mkv\"") | |
else | |
system("ffmpeg -i \"#{name}#{ext}\" -vcodec copy -acodec copy -sn \"#{name}_temp.mkv\"") | |
end | |
# add subtitle | |
system("ffmpeg -i \"#{name}_temp.mkv\" -sub_charenc #{encoding} -i \"#{name}.srt\" -vcodec copy -acodec copy -scodec srt -metadata:s:s:0 language=#{SUB_LANG} -disposition:s:0 default \"#{name}_sub.mkv\"") | |
# delete temporary file | |
system("rm -v \"#{name}_temp.mkv\"") | |
end | |
end | |
# normalze audio in video files | |
def normalize_audio | |
Dir.glob('*.{mp4,avi,mkv}').each do |file| | |
system("ffmpeg -i \"#{file}\" -vcodec copy -ac 2 -af dynaudnorm -acodec aac '#{file}_norm.mp4'") | |
end | |
end | |
# extract m4a audio from mp4 video files | |
def extract_audio | |
Dir.glob("*.mp4").each do |file| | |
system("ffmpeg.exe -i #{file} -vn -acodec copy #{file.sub('.mp4', '.m4a')}") | |
end | |
end | |
# TODO concat video files | |
# $ ffmpeg -f concat -safe 0 -i files.txt -c copy output.mkv | |
# | |
# $ cat files.txt | |
# file 'file 1.mkv' | |
# file 'file 2.mkv' | |
# file 'file 3.mkv' | |
# file 'file 4.mkv' | |
# TODO convert to mp3 music | |
# $ ffmpeg -i input.webm -vn -acodec mp3 -q:a 4 output.mp3 | |
# $ ffmpeg -i file.mp3 -metadata title="Track Title" -metadata artist="Rockstar" -metadata album="Hot Shit" out.mp3 | |
# Extract srt from files | |
# ffmpeg -i #{file} -vn -an -codec:s:0.1 srt #{file.gsub('.mkv', '')}.srt | |
# Convert to vp9 | |
# ffmpeg -i #{file} -c:v libvpx-vp9 -crf 22 -g 240 -b:v 0 -ac 2 -acodec libopus -b:a 112k #{file}.webm | |
# this may have keyframe compression flickering: https://groups.google.com/a/webmproject.org/g/webm-discuss/c/GwsvXJUhyq0 | |
# two-pass vp9 example | |
# ffmpeg -i s1.mkv -vf "crop=960:540" -c:v libvpx-vp9 -b:v 1800k -minrate 900k -maxrate 2610k -g 240 -pass 1 -speed 4 -an -sn -f null /dev/null && ffmpeg -i s1.mkv -vf "crop=960:540" -c:v libvpx-vp9 -b:v 1800k -minrate 900k -maxrate 2610k -g 240 -an -sn -pass 2 -speed 2 o1.webm | |
# Convert to x265 | |
# ffmpeg -i #{file} -c:v libx265 -crf 19 -ac 2 -acodec aac -b:a 112k #{file}.mp4 | |
# merge audio and video | |
# ffmpeg -i video.mkv -i audio.mkv -c:v copy -c:a copy -map 0:v:0 -map 1:a:0 output.mkv | |
# with delay | |
# system("ffmpeg -i #{e[0]} -itsoffset 0.5 -i #{e[1]} -c:v copy -c:a aac -map 0:v:0 -map 1:a:0 out2/#{e[0]}") | |
# You can 'simply' convert the current fps to the desired one using the 'atempo' filter. For example, to achieve a common conversion from PAL (25fps) to NTSC (23.976fps) would be: | |
# 23.976/25 = 0.95904 | |
# So with ffmpeg: | |
# ffmpeg -i input.mkv -filter:a "atempo=0.95904" -af -vn out.mkv | |
# You would also to apply a different most efficient codec. For example maintaing previous parameters but adding codec options: Opus, 224kbps VBR, 5.1 channels: | |
# ffmpeg -i input.mkv -filter:a "atempo=0.95904" -c:a libopus -b:a 224k -vbr 1 -af "ch | |
command = COMMANDS[ARGV[0]] || COMMANDS['help'] | |
command.call(ARGV[1..-1]) |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment