-
-
Save to/a35f45e3fc2548c985435b72b35015e3 to your computer and use it in GitHub Desktop.
| 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 |
4年前のことで 私も 現在 利用していないので まったく わからなくなっちゃってます><
どうにか修正できないかとChatGPTといろいろやりましたが、結果は芳しく無く……
このスクリプトは非常に便利でグレートなものなので、どうにか!どうにか!していただけないでしょうか!
ちなみにChatGPTとの知識皆無な私が行った恥ずかしいやり取りはこちらです(/////)
https://chat.openai.com/share/47f64417-5e7b-41a3-85b5-8ccb46f3e04b
私のほうでOBS Studio 30.2.3でフェードアウト中にすぐにシーンを戻すと再現しました。
ログを差し込んでデバッグをしたところ再現時にsource_showのsignalイベントが発火していないように見受けられました。
コード的に、スタジオモードでの切替時も動作しなさそうです。
OBS自体初心者なのですが、意外に、プラグインなども含めて音声をうまくクロスフェードする手段って提供されていないのですかね?
「高機能シーンスイッチャー」のマクロだと設定しにくかったので、
もう少し探して見当たらなければ私のほうで本スクリプトを参考に書きなおそうかと思います。
ざっと書き直しました。もう少し自分で使ってみてバグが取れたところで、近日中に共有したいと思います。
デフォルトの機能でトランジションのフェード設定さえしていれば音声もフェードイン・フェードアウトしていることに気が付きました。
音声をモニターしているだけではわからないのですが、配信や録画ではフェードが効いているようですね。
一通り書き直していろいろテストしている間に気がつきました・・・!
せっかく作ったスクリプトですが無用ですね。。どこかで供養はしますが。
つまり最新のOBSのトランジションのフェード設定さえしておけば、
今までバツンと音声が切り替わっていたのが、音もフェードして滑らかに切り替わってくれるようになったということですか?
……だとしたらOBS神アプデ!?
それにしてもray34g様スクリプトの見直しと現状の確認作業本当に助かりました。ありがとうございます。神と崇めます。
https://github.com/NagaoSouma/OBS-fade-audio-when-transitioning
1000001901.mp4
OBSを最新にしているものの音声ごとフェードしていることが確認できなかったため、一応トランジション毎(フェード、カット、スティンガーなど)にフェード時間を設定できるスクリプトを公開しました。
スタジオモードでも使えます(スタジオモードの方がいいまである)
OBS 32.1.0でauto_fade_audio.luaを利用したときに、なぜかシーンが完全に切り替わった後に音量が0になってしまっていたので、Geminiに聞いて修正案をこちらに記載しておきます。NagaoSoumaさんのスクリプトの方が良いかもしれませんがご参考まで。
local obs = obslua
-- 設定値
local duration = 1200 -- フェード時間(ms)
local interval = 50 -- タイマー間隔(ms)
local steps = duration / interval
local debug = true
local fade_table = {}
local is_running = false
-- ログ出力用
function log(msg)
if not debug then return end
print("[AutoFade] " .. msg)
end
-- フェード処理のメインループ
function fade_timer_callback()
if fade_table == nil then return end
local current_scene_source = obs.obs_frontend_get_current_scene()
if current_scene_source == nil then return end
local current_scene = obs.obs_scene_from_source(current_scene_source)
for name, _ in pairs(fade_table) do
local source = obs.obs_get_source_by_name(name)
if source ~= nil then
-- このソースが「現在のアクティブシーン」に含まれているか確認
local scene_item = obs.obs_scene_find_source(current_scene, name)
local is_in_active_scene = (scene_item ~= nil)
local volume = obs.obs_source_get_volume(source)
if is_in_active_scene then
-- フェードイン
if volume < 1.0 then
local new_vol = math.min(1.0, volume + (1.0 / steps))
obs.obs_source_set_volume(source, new_vol)
else
fade_table[name] = nil
end
else
-- フェードアウト
if volume > 0.0 then
local new_vol = math.max(0.0, volume - (1.0 / steps))
obs.obs_source_set_volume(source, new_vol)
else
fade_table[name] = nil
end
end
obs.obs_source_release(source)
else
fade_table[name] = nil
end
end
obs.obs_source_release(current_scene_source)
-- 全てのフェードが完了したらタイマー停止
if next(fade_table) == nil then
obs.timer_remove(fade_timer_callback) -- 修正箇所
is_running = false
log("All fades complete. Timer stopped.")
end
end
-- シーンが切り替わった時のイベント
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
log("Scene switch detected: " .. obs.obs_source_get_name(source))
local sources = obs.obs_enum_sources()
if sources ~= nil then
for _, s in ipairs(sources) do
local flags = obs.obs_source_get_output_flags(s)
if bit.band(flags, obs.OBS_SOURCE_AUDIO) ~= 0 then
local s_name = obs.obs_source_get_name(s)
fade_table[s_name] = true
end
end
obs.source_list_release(sources)
end
if not is_running then
obs.timer_add(fade_timer_callback, interval) -- 修正箇所
is_running = true
log("Fade timer started.")
end
end
function script_description()
return "シーン切り替え時に音声を自動フェードイン/アウトします (修正版v2)"
end
function script_load(settings)
local sh = obs.obs_get_signal_handler()
obs.signal_handler_connect(sh, "source_show", on_source_show)
log("Script loaded and signal connected.")
end
便利なスクリプトで実装不可避なのですが問題が発生しております。
フェードアウト後音声設定が-inf dBになって固定される
具体的に記述すると、例えば
この問題は致命的で、シーンを切り替えると音声が出力されなくなってしまい放送に支障出てしまいます。
修正できないでしょうか?