OBS: シーンが切り替わるタイミングでメディアをフェードアウト/フェードインする
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
local obs = obslua | |
local duration = 1200 | |
local interval = 50 | |
local steps = duration / interval | |
local current_scene_name | |
local debug = false | |
local fade_table = {} | |
local is_running = false | |
function on_source_show(calldata) | |
local source = obs.calldata_source(calldata, "source") | |
if source == nil then return end | |
local source_id = obs.obs_source_get_id(source) | |
if source_id ~= "scene" then return end | |
-- 初回の実行か? | |
local next_scene_name = obs.obs_source_get_name(source) | |
if current_scene_name == nil then | |
current_scene_name = next_scene_name | |
return | |
end | |
log("SCENE_SHOW:" .. next_scene_name); | |
-- 古いシーンのメディアを繰り返す | |
local source = obs.obs_get_source_by_name(current_scene_name) | |
for_each_scene_items(source, function(source, source_name) | |
log("FADE_OUT: " .. source_name) | |
-- フェード方向をフェードアウトにする | |
fade_table[source_name].direction = -1 | |
end) | |
obs.obs_source_release(source) | |
-- 新しいシーンのメディアを繰り返す | |
local source = obs.obs_get_source_by_name(next_scene_name) | |
for_each_scene_items(source, function(source, source_name) | |
log("FADE_IN: " .. source_name) | |
-- フェードアウトの途中でなかったか? | |
-- (前後のシーンで同一のメディアがあった場合、フェードがスキップされる) | |
if fade_table[source_name].direction == nil then | |
-- 音量をゼロにする | |
obs.obs_source_set_volume(source, 0) | |
end | |
-- フェード方向をフェードインにする | |
fade_table[source_name].direction = 1 | |
end) | |
obs.obs_source_release(source) | |
start_timer() | |
current_scene_name = next_scene_name | |
end | |
function for_each_scene_items(source, func) | |
local scene = obs.obs_scene_from_source(source) | |
local items = obs.obs_scene_enum_items(scene) | |
for _, item in ipairs(items) do | |
-- メディアソースか? | |
local source = obs.obs_sceneitem_get_source(item) | |
local source_id = obs.obs_source_get_id(source) | |
if source_id == "vlc_source" or source_id == "ffmpeg_source" then | |
local source_name = obs.obs_source_get_name(source) | |
local volume = obs.obs_source_get_volume(source) | |
if not obs.obs_source_muted(source) then | |
if fade_table[source_name] == nil then | |
fade_table[source_name] = {volume = volume} | |
end | |
func(source, source_name) | |
end | |
end | |
end | |
obs.sceneitem_list_release(items) | |
end | |
function start_timer() | |
if table.empty(fade_table) or is_running then return end | |
obs.timer_add(function() | |
for source_name, info in pairs(fade_table) do | |
-- フェードインか? | |
local source = obs.obs_get_source_by_name(source_name) | |
local volume = obs.obs_source_get_volume(source) | |
if info.direction > 0 then | |
volume = math.min(volume + (info.volume / steps), info.volume) | |
-- 最大音量に達しているか? | |
if volume == info.volume then | |
fade_table[source_name] = nil | |
end | |
else | |
volume = math.max(volume - (info.volume / steps), 0) | |
-- メディアの再生が終了しているか? | |
if not obs.obs_source_active(source) then | |
-- 音量を元に戻す | |
volume = info.volume | |
fade_table[source_name] = nil | |
end | |
end | |
obs.obs_source_set_volume(source, volume) | |
obs.obs_source_release(source) | |
end | |
-- 全てのフェードが終了したか? | |
if table.empty(fade_table) then | |
log("TIMER_END:") | |
obs.remove_current_callback() | |
is_running = false | |
end | |
end, interval) | |
log("TIMER_START:") | |
is_running = true | |
end | |
function log(msg) | |
if not debug then return end | |
print(msg) | |
end | |
function script_description() | |
return "auto fade in/out audios" | |
end | |
function script_load(settings) | |
log("LOAD:"); | |
obs.signal_handler_connect( | |
obs.obs_get_signal_handler(), "source_show", on_source_show) | |
end | |
function table.empty(tbl) | |
if tbl == nil then return true end | |
return not next(tbl) | |
end |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment