update reload and add config file
This commit is contained in:
parent
a9b562f8e8
commit
0acea11d35
34
script-opts/reload.conf
Normal file
34
script-opts/reload.conf
Normal file
@ -0,0 +1,34 @@
|
|||||||
|
# enable automatic reload on timeout
|
||||||
|
# when paused-for-cache event fired, we will wait
|
||||||
|
# paused_for_cache_timer_timeout sedonds and then reload the video
|
||||||
|
paused_for_cache_timer_enabled=yes
|
||||||
|
|
||||||
|
# checking paused_for_cache property interval in seconds,
|
||||||
|
# can not be less than 0.05 (50 ms)
|
||||||
|
paused_for_cache_timer_interval=1
|
||||||
|
|
||||||
|
# time in seconds to wait until reload
|
||||||
|
paused_for_cache_timer_timeout=10
|
||||||
|
|
||||||
|
# enable automatic reload based on demuxer cache
|
||||||
|
# if demuxer-cache-time property didn't change in demuxer_cache_timer_timeout
|
||||||
|
# time interval, the video will be reloaded as soon as demuxer cache depleated
|
||||||
|
demuxer_cache_timer_enabled=yes
|
||||||
|
|
||||||
|
# checking demuxer-cache-time property interval in seconds,
|
||||||
|
# can not be less than 0.05 (50 ms)
|
||||||
|
demuxer_cache_timer_interval=2
|
||||||
|
|
||||||
|
# if demuxer cache didn't receive any data during demuxer_cache_timer_timeout
|
||||||
|
# we decide that it has no progress and will reload the stream when
|
||||||
|
# paused_for_cache event happens
|
||||||
|
demuxer_cache_timer_timeout=20
|
||||||
|
|
||||||
|
# when the end-of-file is reached, reload the stream to check
|
||||||
|
# if there is more content available.
|
||||||
|
reload_eof_enabled=no
|
||||||
|
|
||||||
|
# keybinding to reload stream from current time position
|
||||||
|
# you can disable keybinding by setting it to empty value
|
||||||
|
# reload_key_binding=
|
||||||
|
reload_key_binding=Ctrl+r
|
@ -57,12 +57,10 @@
|
|||||||
-- `--msg-level='reload=debug'`. You may also need to add the `--no-msg-color`
|
-- `--msg-level='reload=debug'`. You may also need to add the `--no-msg-color`
|
||||||
-- option to make the debug logs visible if you are using a dark colorscheme
|
-- option to make the debug logs visible if you are using a dark colorscheme
|
||||||
-- in terminal.
|
-- in terminal.
|
||||||
|
|
||||||
local msg = require 'mp.msg'
|
local msg = require 'mp.msg'
|
||||||
local options = require 'mp.options'
|
local options = require 'mp.options'
|
||||||
local utils = require 'mp.utils'
|
local utils = require 'mp.utils'
|
||||||
|
|
||||||
|
|
||||||
local settings = {
|
local settings = {
|
||||||
paused_for_cache_timer_enabled = true,
|
paused_for_cache_timer_enabled = true,
|
||||||
paused_for_cache_timer_interval = 1,
|
paused_for_cache_timer_interval = 1,
|
||||||
@ -71,7 +69,7 @@ local settings = {
|
|||||||
demuxer_cache_timer_interval = 2,
|
demuxer_cache_timer_interval = 2,
|
||||||
demuxer_cache_timer_timeout = 20,
|
demuxer_cache_timer_timeout = 20,
|
||||||
reload_eof_enabled = false,
|
reload_eof_enabled = false,
|
||||||
reload_key_binding = "Ctrl+r",
|
reload_key_binding = "Ctrl+r"
|
||||||
}
|
}
|
||||||
|
|
||||||
-- global state stores properties between reloads
|
-- global state stores properties between reloads
|
||||||
@ -99,11 +97,7 @@ local property_keep_open = nil
|
|||||||
local demuxer_cache = {
|
local demuxer_cache = {
|
||||||
timer = nil,
|
timer = nil,
|
||||||
|
|
||||||
state = {
|
state = { name = 'uninitialized', demuxer_cache_time = 0, in_state_time = 0 },
|
||||||
name = 'uninitialized',
|
|
||||||
demuxer_cache_time = 0,
|
|
||||||
in_state_time = 0,
|
|
||||||
},
|
|
||||||
|
|
||||||
events = {
|
events = {
|
||||||
continue_fetch = { name = 'continue_fetch', from = 'fetch', to = 'fetch' },
|
continue_fetch = { name = 'continue_fetch', from = 'fetch', to = 'fetch' },
|
||||||
@ -112,8 +106,8 @@ local demuxer_cache = {
|
|||||||
fetch_to_stale = { name = 'fetch_to_stale', from = 'fetch', to = 'stale' },
|
fetch_to_stale = { name = 'fetch_to_stale', from = 'fetch', to = 'stale' },
|
||||||
stale_to_fetch = { name = 'stale_to_fetch', from = 'stale', to = 'fetch' },
|
stale_to_fetch = { name = 'stale_to_fetch', from = 'stale', to = 'fetch' },
|
||||||
stale_to_stuck = { name = 'stale_to_stuck', from = 'stale', to = 'stuck' },
|
stale_to_stuck = { name = 'stale_to_stuck', from = 'stale', to = 'stuck' },
|
||||||
stuck_to_fetch = { name = 'stuck_to_fetch', from = 'stuck', to = 'fetch' },
|
stuck_to_fetch = { name = 'stuck_to_fetch', from = 'stuck', to = 'fetch' }
|
||||||
},
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -122,7 +116,7 @@ function demuxer_cache.reset_state()
|
|||||||
demuxer_cache.state = {
|
demuxer_cache.state = {
|
||||||
name = demuxer_cache.events.continue_fetch.to,
|
name = demuxer_cache.events.continue_fetch.to,
|
||||||
demuxer_cache_time = 0,
|
demuxer_cache_time = 0,
|
||||||
in_state_time = 0,
|
in_state_time = 0
|
||||||
}
|
}
|
||||||
end
|
end
|
||||||
|
|
||||||
@ -145,16 +139,21 @@ end
|
|||||||
|
|
||||||
function demuxer_cache.transition(event)
|
function demuxer_cache.transition(event)
|
||||||
if demuxer_cache.state.name == event.from then
|
if demuxer_cache.state.name == event.from then
|
||||||
|
|
||||||
-- state setup
|
-- state setup
|
||||||
demuxer_cache.state.demuxer_cache_time = event.demuxer_cache_time
|
demuxer_cache.state.demuxer_cache_time = event.demuxer_cache_time
|
||||||
|
|
||||||
if event.name == 'continue_fetch' then
|
if event.name == 'continue_fetch' then
|
||||||
demuxer_cache.state.in_state_time = demuxer_cache.state.in_state_time + event.interval
|
demuxer_cache.state.in_state_time = demuxer_cache.state
|
||||||
|
.in_state_time +
|
||||||
|
event.interval
|
||||||
elseif event.name == 'continue_stale' then
|
elseif event.name == 'continue_stale' then
|
||||||
demuxer_cache.state.in_state_time = demuxer_cache.state.in_state_time + event.interval
|
demuxer_cache.state.in_state_time = demuxer_cache.state
|
||||||
|
.in_state_time +
|
||||||
|
event.interval
|
||||||
elseif event.name == 'continue_stuck' then
|
elseif event.name == 'continue_stuck' then
|
||||||
demuxer_cache.state.in_state_time = demuxer_cache.state.in_state_time + event.interval
|
demuxer_cache.state.in_state_time = demuxer_cache.state
|
||||||
|
.in_state_time +
|
||||||
|
event.interval
|
||||||
elseif event.name == 'fetch_to_stale' then
|
elseif event.name == 'fetch_to_stale' then
|
||||||
demuxer_cache.state.in_state_time = 0
|
demuxer_cache.state.in_state_time = 0
|
||||||
elseif event.name == 'stale_to_fetch' then
|
elseif event.name == 'stale_to_fetch' then
|
||||||
@ -168,33 +167,32 @@ function demuxer_cache.transition(event)
|
|||||||
-- state transition
|
-- state transition
|
||||||
demuxer_cache.state.name = event.to
|
demuxer_cache.state.name = event.to
|
||||||
|
|
||||||
msg.debug('demuxer_cache.transition', event.name, utils.to_string(demuxer_cache.state))
|
msg.debug('demuxer_cache.transition', event.name,
|
||||||
|
utils.to_string(demuxer_cache.state))
|
||||||
else
|
else
|
||||||
msg.error(
|
msg.error('demuxer_cache.transition', 'illegal transition', event.name,
|
||||||
'demuxer_cache.transition',
|
|
||||||
'illegal transition', event.name,
|
|
||||||
'from state', demuxer_cache.state.name)
|
'from state', demuxer_cache.state.name)
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
function demuxer_cache.initialize(demuxer_cache_timer_interval)
|
function demuxer_cache.initialize(demuxer_cache_timer_interval)
|
||||||
demuxer_cache.reset_state()
|
demuxer_cache.reset_state()
|
||||||
demuxer_cache.timer = mp.add_periodic_timer(
|
demuxer_cache.timer = mp.add_periodic_timer(demuxer_cache_timer_interval,
|
||||||
demuxer_cache_timer_interval,
|
|
||||||
function()
|
function()
|
||||||
demuxer_cache.demuxer_cache_timer_tick(
|
demuxer_cache.demuxer_cache_timer_tick(
|
||||||
mp.get_property_native('demuxer-cache-time'),
|
mp.get_property_native('demuxer-cache-time'),
|
||||||
demuxer_cache_timer_interval)
|
demuxer_cache_timer_interval)
|
||||||
end
|
end)
|
||||||
)
|
|
||||||
end
|
end
|
||||||
|
|
||||||
-- If there is no progress of demuxer_cache_time in
|
-- If there is no progress of demuxer_cache_time in
|
||||||
-- settings.demuxer_cache_timer_timeout time interval switch state to
|
-- settings.demuxer_cache_timer_timeout time interval switch state to
|
||||||
-- 'stuck' and switch back to 'fetch' as soon as any progress is made
|
-- 'stuck' and switch back to 'fetch' as soon as any progress is made
|
||||||
function demuxer_cache.demuxer_cache_timer_tick(demuxer_cache_time, demuxer_cache_timer_interval)
|
function demuxer_cache.demuxer_cache_timer_tick(demuxer_cache_time,
|
||||||
|
demuxer_cache_timer_interval)
|
||||||
local event = nil
|
local event = nil
|
||||||
local cache_has_progress = demuxer_cache.has_progress_since(demuxer_cache_time)
|
local cache_has_progress = demuxer_cache.has_progress_since(
|
||||||
|
demuxer_cache_time)
|
||||||
|
|
||||||
-- I miss pattern matching so much
|
-- I miss pattern matching so much
|
||||||
if demuxer_cache.is_state_fetch() then
|
if demuxer_cache.is_state_fetch() then
|
||||||
@ -206,7 +204,8 @@ function demuxer_cache.demuxer_cache_timer_tick(demuxer_cache_time, demuxer_cach
|
|||||||
elseif demuxer_cache.is_state_stale() then
|
elseif demuxer_cache.is_state_stale() then
|
||||||
if cache_has_progress then
|
if cache_has_progress then
|
||||||
event = demuxer_cache.events.stale_to_fetch
|
event = demuxer_cache.events.stale_to_fetch
|
||||||
elseif demuxer_cache.state.in_state_time < settings.demuxer_cache_timer_timeout then
|
elseif demuxer_cache.state.in_state_time <
|
||||||
|
settings.demuxer_cache_timer_timeout then
|
||||||
event = demuxer_cache.events.continue_stale
|
event = demuxer_cache.events.continue_stale
|
||||||
else
|
else
|
||||||
event = demuxer_cache.events.stale_to_stuck
|
event = demuxer_cache.events.stale_to_stuck
|
||||||
@ -224,11 +223,7 @@ function demuxer_cache.demuxer_cache_timer_tick(demuxer_cache_time, demuxer_cach
|
|||||||
demuxer_cache.transition(event)
|
demuxer_cache.transition(event)
|
||||||
end
|
end
|
||||||
|
|
||||||
|
local paused_for_cache = { timer = nil, time = 0 }
|
||||||
local paused_for_cache = {
|
|
||||||
timer = nil,
|
|
||||||
time = 0,
|
|
||||||
}
|
|
||||||
|
|
||||||
function paused_for_cache.reset_timer()
|
function paused_for_cache.reset_timer()
|
||||||
msg.debug('paused_for_cache.reset_timer', paused_for_cache.time)
|
msg.debug('paused_for_cache.reset_timer', paused_for_cache.time)
|
||||||
@ -242,8 +237,7 @@ end
|
|||||||
function paused_for_cache.start_timer(interval_seconds, timeout_seconds)
|
function paused_for_cache.start_timer(interval_seconds, timeout_seconds)
|
||||||
msg.debug('paused_for_cache.start_timer', paused_for_cache.time)
|
msg.debug('paused_for_cache.start_timer', paused_for_cache.time)
|
||||||
if not paused_for_cache.timer then
|
if not paused_for_cache.timer then
|
||||||
paused_for_cache.timer = mp.add_periodic_timer(
|
paused_for_cache.timer = mp.add_periodic_timer(interval_seconds,
|
||||||
interval_seconds,
|
|
||||||
function()
|
function()
|
||||||
paused_for_cache.time = paused_for_cache.time + interval_seconds
|
paused_for_cache.time = paused_for_cache.time + interval_seconds
|
||||||
if paused_for_cache.time >= timeout_seconds then
|
if paused_for_cache.time >= timeout_seconds then
|
||||||
@ -251,14 +245,12 @@ function paused_for_cache.start_timer(interval_seconds, timeout_seconds)
|
|||||||
reload_resume()
|
reload_resume()
|
||||||
end
|
end
|
||||||
msg.debug('paused_for_cache', 'tick', paused_for_cache.time)
|
msg.debug('paused_for_cache', 'tick', paused_for_cache.time)
|
||||||
end
|
end)
|
||||||
)
|
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
function paused_for_cache.handler(property, is_paused)
|
function paused_for_cache.handler(property, is_paused)
|
||||||
if is_paused then
|
if is_paused then
|
||||||
|
|
||||||
if demuxer_cache.is_state_stuck() then
|
if demuxer_cache.is_state_stuck() then
|
||||||
msg.info("demuxer cache has no progress")
|
msg.info("demuxer cache has no progress")
|
||||||
-- reset demuxer state to avoid immediate reload if
|
-- reset demuxer state to avoid immediate reload if
|
||||||
@ -267,8 +259,7 @@ function paused_for_cache.handler(property, is_paused)
|
|||||||
reload_resume()
|
reload_resume()
|
||||||
end
|
end
|
||||||
|
|
||||||
paused_for_cache.start_timer(
|
paused_for_cache.start_timer(settings.paused_for_cache_timer_interval,
|
||||||
settings.paused_for_cache_timer_interval,
|
|
||||||
settings.paused_for_cache_timer_timeout)
|
settings.paused_for_cache_timer_timeout)
|
||||||
else
|
else
|
||||||
paused_for_cache.reset_timer()
|
paused_for_cache.reset_timer()
|
||||||
@ -285,8 +276,15 @@ function reload(path, time_pos)
|
|||||||
if time_pos == nil then
|
if time_pos == nil then
|
||||||
mp.commandv("loadfile", path, "replace")
|
mp.commandv("loadfile", path, "replace")
|
||||||
else
|
else
|
||||||
|
local success = mp.commandv("loadfile", path, "replace", -1,
|
||||||
|
"start=+" .. time_pos)
|
||||||
|
-- fallback to old syntax of loadfile for compatibility
|
||||||
|
if success == nil then
|
||||||
|
msg.warn(
|
||||||
|
"old loadfile syntax detected. falling back to using old syntax. update mpv to remove this warning")
|
||||||
mp.commandv("loadfile", path, "replace", "start=+" .. time_pos)
|
mp.commandv("loadfile", path, "replace", "start=+" .. time_pos)
|
||||||
end
|
end
|
||||||
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
function reload_resume()
|
function reload_resume()
|
||||||
@ -297,7 +295,7 @@ function reload_resume()
|
|||||||
local playlist_count = mp.get_property_number("playlist/count")
|
local playlist_count = mp.get_property_number("playlist/count")
|
||||||
local playlist_pos = mp.get_property_number("playlist-pos")
|
local playlist_pos = mp.get_property_number("playlist-pos")
|
||||||
local playlist = {}
|
local playlist = {}
|
||||||
for i = 0, playlist_count-1 do
|
for i = 0, playlist_count - 1 do
|
||||||
playlist[i] = mp.get_property("playlist/" .. i .. "/filename")
|
playlist[i] = mp.get_property("playlist/" .. i .. "/filename")
|
||||||
end
|
end
|
||||||
-- Tries to determine live stream vs. pre-recordered VOD. VOD has non-zero
|
-- Tries to determine live stream vs. pre-recordered VOD. VOD has non-zero
|
||||||
@ -319,12 +317,12 @@ function reload_resume()
|
|||||||
msg.info("reloading stream")
|
msg.info("reloading stream")
|
||||||
reload(path, nil)
|
reload(path, nil)
|
||||||
end
|
end
|
||||||
msg.info("file ", playlist_pos+1, "of", playlist_count, "in playlist")
|
msg.info("file", playlist_pos + 1, "of", playlist_count, "in playlist")
|
||||||
for i = 0, playlist_pos-1 do
|
for i = 0, playlist_pos - 1 do
|
||||||
mp.commandv("loadfile", playlist[i], "append")
|
mp.commandv("loadfile", playlist[i], "append")
|
||||||
end
|
end
|
||||||
mp.commandv("playlist-move", 0, playlist_pos+1)
|
mp.commandv("playlist-move", 0, playlist_pos + 1)
|
||||||
for i = playlist_pos+1, playlist_count-1 do
|
for i = playlist_pos + 1, playlist_count - 1 do
|
||||||
mp.commandv("loadfile", playlist[i], "append")
|
mp.commandv("loadfile", playlist[i], "append")
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
@ -334,15 +332,14 @@ function reload_eof(property, eof_reached)
|
|||||||
local time_pos = mp.get_property_number("time-pos")
|
local time_pos = mp.get_property_number("time-pos")
|
||||||
local duration = mp.get_property_number("duration")
|
local duration = mp.get_property_number("duration")
|
||||||
|
|
||||||
if eof_reached and math.floor(time_pos) == math.floor(duration) then
|
if eof_reached and round(time_pos) == round(duration) then
|
||||||
msg.debug("property_time_pos", property_time_pos, "time_pos", time_pos)
|
msg.debug("property_time_pos", property_time_pos, "time_pos", time_pos)
|
||||||
|
|
||||||
-- Check that playback time_pos made progress after the last reload. When
|
-- Check that playback time_pos made progress after the last reload. When
|
||||||
-- eof is reached we try to reload video, in case there is more content
|
-- eof is reached we try to reload the video, in case there is more content
|
||||||
-- available. If time_pos stayed the same after reload, it means that vidkk
|
-- available. If time_pos stayed the same after reload, it means that the
|
||||||
-- to avoid infinite reload loop when playback ended
|
-- video length stayed the same, and we can end the playback.
|
||||||
-- math.floor function rounds time_pos to a second, to avoid inane reloads
|
if round(property_time_pos) == round(time_pos) then
|
||||||
if math.floor(property_time_pos) == math.floor(time_pos) then
|
|
||||||
msg.info("eof reached, playback ended")
|
msg.info("eof reached, playback ended")
|
||||||
mp.set_property("keep-open", property_keep_open)
|
mp.set_property("keep-open", property_keep_open)
|
||||||
else
|
else
|
||||||
@ -364,7 +361,7 @@ function on_file_loaded(event)
|
|||||||
seekable = mp.get_property("seekable"),
|
seekable = mp.get_property("seekable"),
|
||||||
pause = mp.get_property("pause"),
|
pause = mp.get_property("pause"),
|
||||||
paused_for_cache = mp.get_property("paused-for-cache"),
|
paused_for_cache = mp.get_property("paused-for-cache"),
|
||||||
cache_buffering_state = mp.get_property("cache-buffering-state"),
|
cache_buffering_state = mp.get_property("cache-buffering-state")
|
||||||
}
|
}
|
||||||
msg.debug("debug_info", utils.to_string(debug_info))
|
msg.debug("debug_info", utils.to_string(debug_info))
|
||||||
|
|
||||||
@ -380,12 +377,16 @@ function on_file_loaded(event)
|
|||||||
mp.commandv("keypress", 'SPACE')
|
mp.commandv("keypress", 'SPACE')
|
||||||
end
|
end
|
||||||
|
|
||||||
|
-- Round positive numbers.
|
||||||
|
function round(num) return math.floor(num + 0.5) end
|
||||||
|
|
||||||
-- main
|
-- main
|
||||||
|
|
||||||
read_settings()
|
read_settings()
|
||||||
|
|
||||||
if settings.reload_key_binding ~= "" then
|
if settings.reload_key_binding ~= "" then
|
||||||
mp.add_key_binding(settings.reload_key_binding, "reload_resume", reload_resume)
|
mp.add_key_binding(settings.reload_key_binding, "reload_resume",
|
||||||
|
reload_resume)
|
||||||
end
|
end
|
||||||
|
|
||||||
if settings.paused_for_cache_timer_enabled then
|
if settings.paused_for_cache_timer_enabled then
|
||||||
@ -398,10 +399,7 @@ end
|
|||||||
|
|
||||||
if settings.reload_eof_enabled then
|
if settings.reload_eof_enabled then
|
||||||
-- vo-configured == video output created && its configuration went ok
|
-- vo-configured == video output created && its configuration went ok
|
||||||
mp.observe_property(
|
mp.observe_property("vo-configured", "bool", function(name, vo_configured)
|
||||||
"vo-configured",
|
|
||||||
"bool",
|
|
||||||
function(name, vo_configured)
|
|
||||||
msg.debug(name, vo_configured)
|
msg.debug(name, vo_configured)
|
||||||
if vo_configured then
|
if vo_configured then
|
||||||
property_path = mp.get_property("path")
|
property_path = mp.get_property("path")
|
||||||
@ -409,10 +407,10 @@ if settings.reload_eof_enabled then
|
|||||||
mp.set_property("keep-open", "yes")
|
mp.set_property("keep-open", "yes")
|
||||||
mp.set_property("keep-open-pause", "no")
|
mp.set_property("keep-open-pause", "no")
|
||||||
end
|
end
|
||||||
end
|
end)
|
||||||
)
|
|
||||||
|
|
||||||
mp.observe_property("eof-reached", "bool", reload_eof)
|
mp.observe_property("eof-reached", "bool", reload_eof)
|
||||||
end
|
end
|
||||||
|
|
||||||
mp.register_event("file-loaded", on_file_loaded)
|
mp.register_event("file-loaded", on_file_loaded)
|
||||||
|
|
||||||
|
Loading…
x
Reference in New Issue
Block a user