195 lines
6 KiB
Lua
195 lines
6 KiB
Lua
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')
|
|
start_time = start_time - padding
|
|
end_time = end_time + padding
|
|
|
|
if start_time < 0 then
|
|
start_time = 0
|
|
end
|
|
|
|
if end_time > video_duration then
|
|
end_time = video_duration
|
|
end
|
|
|
|
return start_time, end_time
|
|
end
|
|
|
|
local get_active_track = function(track_type)
|
|
local track_list = mp.get_property_native('track-list')
|
|
for _, track in pairs(track_list) do
|
|
if track.type == track_type and track.selected == true then
|
|
return track
|
|
end
|
|
end
|
|
return nil
|
|
end
|
|
|
|
------------------------------------------------------------
|
|
-- 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']
|
|
|
|
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),
|
|
output_path
|
|
}
|
|
end
|
|
|
|
------------------------------------------------------------
|
|
-- mpv encoder
|
|
|
|
local mpv = {}
|
|
|
|
mpv.make_snapshot_args = function(source_path, output_path, timestamp)
|
|
return {
|
|
'mpv',
|
|
source_path,
|
|
'--loop-file=no',
|
|
'--audio=no',
|
|
'--no-ocopy-metadata',
|
|
'--no-sub',
|
|
'--frames=1',
|
|
'--ovcopts-add=lossless=0',
|
|
'--ovcopts-add=compression_level=6',
|
|
table.concat { '--ovc=', _config.snapshot_codec },
|
|
table.concat { '-start=', timestamp },
|
|
table.concat { '--ovcopts-add=quality=', tostring(_config.snapshot_quality) },
|
|
table.concat { '--vf-add=scale=', _config.snapshot_width, ':', _config.snapshot_height },
|
|
table.concat { '-o=', output_path }
|
|
}
|
|
end
|
|
|
|
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")
|
|
|
|
if audio_track and audio_track.external == true then
|
|
source_path = audio_track['external-filename']
|
|
audio_track_id = 'auto'
|
|
end
|
|
|
|
return {
|
|
'mpv',
|
|
source_path,
|
|
'--loop-file=no',
|
|
'--video=no',
|
|
'--no-ocopy-metadata',
|
|
'--no-sub',
|
|
'--audio-channels=mono',
|
|
'--oacopts-add=vbr=on',
|
|
'--oacopts-add=application=voip',
|
|
'--oacopts-add=compression_level=10',
|
|
table.concat { '--oac=', _config.audio_codec },
|
|
table.concat { '--start=', start_timestamp },
|
|
table.concat { '--end=', end_timestamp },
|
|
table.concat { '--aid=', audio_track_id },
|
|
table.concat { '--volume=', _config.tie_volumes and mp.get_property('volume') or '100' },
|
|
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)
|
|
for arg in string.gmatch(_config.use_ffmpeg and _config.ffmpeg_audio_args or _config.mpv_audio_args, "%S+") do
|
|
-- Prepend before output path
|
|
table.insert(args, #args, arg)
|
|
end
|
|
local on_finish = function()
|
|
_store_fn(filename, output_path)
|
|
os.remove(output_path)
|
|
end
|
|
_subprocess(args, on_finish)
|
|
end
|
|
|
|
local init = function(config, store_fn, os_temp_dir, subprocess)
|
|
_config = config
|
|
_store_fn = store_fn
|
|
_os_temp_dir = os_temp_dir
|
|
_subprocess = subprocess
|
|
encoder = config.use_ffmpeg and ffmpeg or mpv
|
|
end
|
|
|
|
return {
|
|
init = init,
|
|
create_snapshot = create_snapshot,
|
|
create_audio = create_audio,
|
|
}
|