Commit: 39d9c598e7539698a71262e40743bcfa896da51d
Parent: 27f0b567d61a04d54b6b0db9ad7e3aa31e3bbbe9
Author: Ren Tatsumoto
Date:   Sun, 24 Oct 2021 14:41:41 +0300
bring back ffmpeg encoder
for those users who can't obtain an mpv build with the encoder built-in
Diffstat:
| M | encoder.lua | | | 116 | +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++------------ | 
| M | subs2srs.lua | | | 1 | + | 
2 files changed, 100 insertions(+), 17 deletions(-)
diff --git a/encoder.lua b/encoder.lua
@@ -1,6 +1,10 @@
 local mp = require('mp')
 local utils = require('mp.utils')
 local _config, _store_fn, _os_temp_dir, _subprocess
+local encoder
+
+------------------------------------------------------------
+-- utility functions
 
 local pad_timings = function(padding, start_time, end_time)
     local video_duration = mp.get_property_number('duration')
@@ -28,11 +32,73 @@ local get_active_track = function(track_type)
     return nil
 end
 
-local create_snapshot = function(timestamp, filename)
-    local source_path = mp.get_property("path")
-    local output_path = utils.join_path(_os_temp_dir(), filename)
+------------------------------------------------------------
+-- ffmpeg encoder
+
+local ffmpeg = {}
+
+ffmpeg.prefix = { "ffmpeg", "-hide_banner", "-nostdin", "-y", "-loglevel", "quiet", "-sn", }
+
+ffmpeg.prepend = function(args)
+    if next(args) ~= nil then
+        for i, value in ipairs(ffmpeg.prefix) do
+            table.insert(args, i, value)
+        end
+    end
+    return args
+end
+
+ffmpeg.make_snapshot_args = function(source_path, output_path, timestamp)
+    return ffmpeg.prepend {
+        '-an',
+        '-ss', tostring(timestamp),
+        '-i', source_path,
+        '-map_metadata', '-1',
+        '-vcodec', _config.snapshot_codec,
+        '-lossless', '0',
+        '-compression_level', '6',
+        '-qscale:v', tostring(_config.snapshot_quality),
+        '-vf', string.format('scale=%d:%d', _config.snapshot_width, _config.snapshot_height),
+        '-vframes', '1',
+        output_path
+    }
+end
+
+ffmpeg.make_audio_args = function(source_path, output_path, start_timestamp, end_timestamp)
+    local audio_track = get_active_track('audio')
+    local audio_track_id = audio_track['ff-index']
 
-    local args = {
+    if audio_track and audio_track.external == true then
+        source_path = audio_track['external-filename']
+        audio_track_id = 'a'
+    end
+
+    return ffmpeg.prepend {
+        '-vn',
+        '-ss', tostring(start_timestamp),
+        '-to', tostring(end_timestamp),
+        '-i', source_path,
+        '-map_metadata', '-1',
+        '-map', string.format("0:%d", audio_track_id),
+        '-ac', '1',
+        '-codec:a', _config.audio_codec,
+        '-vbr', 'on',
+        '-compression_level', '10',
+        '-application', 'voip',
+        '-b:a', tostring(_config.audio_bitrate),
+        '-filter:a', string.format("volume=%.1f", _config.tie_volumes and mp.get_property_native('volume') / 100 or 1),
+        '-af', 'silenceremove=1:0:-50dB',
+        output_path
+    }
+end
+
+------------------------------------------------------------
+-- mpv encoder
+
+local mpv = {}
+
+mpv.make_snapshot_args = function(source_path, output_path, timestamp)
+    return {
         'mpv',
         source_path,
         '--loop-file=no',
@@ -48,29 +114,18 @@ local create_snapshot = function(timestamp, filename)
         table.concat { '--vf-add=scale=', _config.snapshot_width, ':', _config.snapshot_height },
         table.concat { '-o=', output_path }
     }
-    local on_finish = function()
-        _store_fn(filename, output_path)
-        os.remove(output_path)
-    end
-    _subprocess(args, on_finish)
 end
 
-local create_audio = function(start_timestamp, end_timestamp, filename, padding)
-    local source_path = mp.get_property("path")
+mpv.make_audio_args = function(source_path, output_path, start_timestamp, end_timestamp)
     local audio_track = get_active_track('audio')
     local audio_track_id = mp.get_property("aid")
-    local output_path = utils.join_path(_os_temp_dir(), filename)
 
     if audio_track and audio_track.external == true then
         source_path = audio_track['external-filename']
         audio_track_id = 'auto'
     end
 
-    if padding > 0 then
-        start_timestamp, end_timestamp = pad_timings(padding, start_timestamp, end_timestamp)
-    end
-
-    local args = {
+    return {
         'mpv',
         source_path,
         '--loop-file=no',
@@ -81,6 +136,7 @@ local create_audio = function(start_timestamp, end_timestamp, filename, padding)
         '--oacopts-add=vbr=on',
         '--oacopts-add=application=voip',
         '--oacopts-add=compression_level=10',
+        '--af-append=silenceremove=1:0:-50dB',
         table.concat { '--oac=', _config.audio_codec },
         table.concat { '--start=', start_timestamp },
         table.concat { '--end=', end_timestamp },
@@ -89,6 +145,31 @@ local create_audio = function(start_timestamp, end_timestamp, filename, padding)
         table.concat { '--oacopts-add=b=', _config.audio_bitrate },
         table.concat { '-o=', output_path }
     }
+end
+
+------------------------------------------------------------
+-- main interface
+
+local create_snapshot = function(timestamp, filename)
+    local source_path = mp.get_property("path")
+    local output_path = utils.join_path(_os_temp_dir(), filename)
+    local args = encoder.make_snapshot_args(source_path, output_path, timestamp)
+    local on_finish = function()
+        _store_fn(filename, output_path)
+        os.remove(output_path)
+    end
+    _subprocess(args, on_finish)
+end
+
+local create_audio = function(start_timestamp, end_timestamp, filename, padding)
+    local source_path = mp.get_property("path")
+    local output_path = utils.join_path(_os_temp_dir(), filename)
+
+    if padding > 0 then
+        start_timestamp, end_timestamp = pad_timings(padding, start_timestamp, end_timestamp)
+    end
+
+    local args = encoder.make_audio_args(source_path, output_path, start_timestamp, end_timestamp)
     local on_finish = function()
         _store_fn(filename, output_path)
         os.remove(output_path)
@@ -101,6 +182,7 @@ local init = function(config, store_fn, os_temp_dir, subprocess)
     _store_fn = store_fn
     _os_temp_dir = os_temp_dir
     _subprocess = subprocess
+    encoder = config.use_ffmpeg and ffmpeg or mpv
 end
 
 return {
diff --git a/subs2srs.lua b/subs2srs.lua
@@ -40,6 +40,7 @@ local config = {
     autoclip = false, -- enable copying subs to the clipboard when mpv starts
     nuke_spaces = true, -- remove all spaces from exported anki cards
     clipboard_trim_enabled = true, -- remove unnecessary characters from strings before copying to the clipboard
+    use_ffmpeg = false, -- if set to true, use ffmpeg to create audio clips and snapshots. by default use mpv.
     snapshot_format = "webp", -- webp or jpg
     snapshot_quality = 15, -- from 0=lowest to 100=highest
     snapshot_width = -2, -- a positive integer or -2 for auto