有一个Python脚本,它通过将完整的重播调整到一个设定的长度来添加3个额外的重播缓冲区长度。以下是完整的脚本:
#!/usr/bin/env python
# title : AdditionalReplays.py
# description : Adds 3 \"additional\" ReplayBuffer.
# author : Bootscreen
# date : 2019 05 11
# version : 0.1
# dependencies : - Python 3.6 (https://www.python.org/ or https://www.python.org/ftp/python/3.6.0/python-3.6.0-amd64-webinstall.exe)
# notes : Follow this step for this script to work:
# : Python:
# : 1. Install python (v3.6 and 64 bits, this is important)
# : 2. Install moviepy (pip install moviepy)
# : OBS:
# : 1. Go to Tools › Scripts
# : 2. Click the "Python Settings" tab
# : 3. Select your python install path
# : 4. Click the "Scripts" tab
# : 5. Click the "+" button and add this script
# : 6. Set the seconds and where it should be saved
# : 7. Set Hotkeys in OBS Settings
# : 8. Check "Enable"
# :
# python_version : 3.6+
# ==============================================================================
import obspython as obs
import os, sys, subprocess, time
from time import sleep
from shutil import copyfile
from importlib import util
from datetime import datetime
enabled = True
debug_mode = False
replay1_hotkey = obs.OBS_INVALID_HOTKEY_ID
replay1_seconds = 60
replay1_path = "R:/"
replay1_remove = False
replay1_from_end = False
replay2_hotkey = obs.OBS_INVALID_HOTKEY_ID
replay2_seconds = 180
replay2_path = "R:/"
replay2_remove = True
replay2_from_end = False
replay3_hotkey = obs.OBS_INVALID_HOTKEY_ID
replay3_seconds = 300
replay3_path = "R:/"
replay3_remove = True
replay3_from_end = False
def file_in_use(fpath):
if os.path.exists(fpath):
try:
os.rename(fpath, fpath)
return False
except:
return True
def ffmpeg_extract_subclip(filename, t1, t2, targetname=None):
if "get_setting" not in sys.modules:
from moviepy.config import get_setting
if "get_setting" not in sys.modules:
from moviepy.tools import subprocess_call
""" Makes a new video file playing video file ``filename`` between
the times ``t1`` and ``t2``. """
name, ext = os.path.splitext(filename)
if not targetname:
T1, T2 = [int(1000*t) for t in [t1, t2]]
targetname = "%sSUB%d_%d.%s" % (name, T1, T2, ext)
cmd = [get_setting("FFMPEG_BINARY"),"-y",
"-ss", "%0.2f"%t1,
"-i", filename,
"-t", "%0.2f"%(t2-t1),
"-vcodec", "copy", "-acodec", "copy", targetname]
if debug_mode:
subprocess_call(cmd)
else:
subprocess_call(cmd, None)
def check_and_install_package(package):
if not check_package(package):
install_package(package)
def check_package(package):
if util.find_spec(package) is None:
return False
else:
return True
def install_package(package):
python_path = os.path.join(sys.prefix ,"python.exe")
subprocess.call([python_path , "-m", "pip", "install", package])
def install_needed(prop, props):
install_package("moviepy")
from moviepy.config import get_setting
from moviepy.tools import subprocess_call
from moviepy.editor import VideoFileClip
def save_and_get_last_replay():
timestamp = time.time()
obs.obs_frontend_replay_buffer_save()
path = get_last_replay()
if not os.path.exists(path):
sleep(2)
path = get_last_replay()
for i in range(20):
file_timestamp = os.path.getctime(path)
if file_timestamp < timestamp:
sleep(1)
path = get_last_replay()
else:
break
file_timestamp = os.path.getctime(path)
if file_timestamp < timestamp:
return None
else:
return path
def get_last_replay():
sleep(10)
replay_buffer = obs.obs_frontend_get_replay_buffer_output()
cd = obs.calldata_create()
ph = obs.obs_output_get_proc_handler(replay_buffer)
path = obs.calldata_string(cd, "path")
obs.proc_handler_call(ph, "get_last_replay", cd)
obs.calldata_destroy(cd)
obs.obs_output_release(replay_buffer)
return path
def save_replay1(pressed):
if pressed and enabled:
save_replay(replay1_seconds, replay1_path, replay1_remove, replay1_from_end)
def save_replay2(pressed):
if pressed and enabled:
save_replay(replay2_seconds, replay2_path, replay2_remove, replay2_from_end)
def save_replay3(pressed):
if pressed and enabled:
save_replay(replay3_seconds, replay3_path, replay3_remove, replay3_from_end)
def save_replay(seconds, new_path, remove, from_end):
global debug_mode
if debug_mode:
print("[AR] save_replay")
print("[AR] seconds=" + str(seconds) )
print("[AR] path=" + new_path)
print("[AR] remove=%s" %(remove))
print("[AR] from_end=%s" %(from_end))
if not enabled:
return
if obs.obs_frontend_replay_buffer_active() is False:
if debug_mode: print("[AR] replaybuffer not active")
return
if seconds > 0:
if "VideoFileClip" not in sys.modules:
from moviepy.config import get_setting
from moviepy.tools import subprocess_call
from moviepy.editor import VideoFileClip
last_replay = save_and_get_last_replay()
if last_replay is not None and len(last_replay) > 0:
if debug_mode:
print("[AR] last_replay=" + last_replay)
last_replay_folder = os.path.dirname(os.path.abspath(last_replay))
last_replay_name, last_replay_type = os.path.splitext(os.path.basename(last_replay))
if len(new_path) <= 0 or not os.path.exists(new_path):
new_path = last_replay_folder
if debug_mode:
print("[AR] last_replay_folder=" + last_replay_folder)
print("[AR] last_replay_name=" + last_replay_name)
print("[AR] last_replay_type=" + last_replay_type)
print("[AR] new_path=" + new_path)
if last_replay_folder == new_path:
new_replay = os.path.join(new_path, last_replay_name + "_" + seconds + "s" + last_replay_type)
else:
new_replay = os.path.join(new_path, last_replay_name + last_replay_type)
if debug_mode:
print("[AR] last_replay=" + last_replay)
print("[AR] new_replay=" + new_replay)
clip = VideoFileClip(last_replay)
duration = clip.duration
if duration > seconds:
if from_end:
if debug_mode: print("[AR] from_end")
ffmpeg_extract_subclip(last_replay, duration - seconds, duration, targetname=new_replay)
else:
if debug_mode: print("[AR] from_begin")
ffmpeg_extract_subclip(last_replay, 0, seconds, targetname=new_replay)
else:
copyfile(last_replay, new_replay)
clip.reader.close()
if clip.audio and clip.audio.reader:
clip.audio.reader.close_proc()
del clip.reader
del clip
if remove and os.path.exists(new_replay):
try:
if debug_mode: print("[AR] try remove")
for x in range(10):
if not file_in_use(last_replay):
break
if debug_mode: print("[AR] file not writeable, wait 0.5 seconds")
sleep(0.5)
if debug_mode: print("[AR] delete file:" + last_replay)
os.remove(last_replay)
except:
print("[AR] error ", sys.exc_info()[0], " on remove : ", last_replay)
def script_defaults(settings):
global global_settings
global debug_mode
if debug_mode: print("[AR] Loaded defaults.")
obs.obs_data_set_default_bool(settings, "enabled", enabled)
obs.obs_data_set_default_bool(settings, "debug_mode", debug_mode)
obs.obs_data_set_default_int(settings, "replay1_seconds", replay1_seconds)
obs.obs_data_set_default_int(settings, "replay2_seconds", replay2_seconds)
obs.obs_data_set_default_int(settings, "replay3_seconds", replay3_seconds)
obs.obs_data_set_default_bool(settings, "replay1_remove", replay1_remove)
obs.obs_data_set_default_bool(settings, "replay2_remove", replay2_remove)
obs.obs_data_set_default_bool(settings, "replay3_remove", replay3_remove)
obs.obs_data_set_default_bool(settings, "replay1_from_end", replay1_from_end)
obs.obs_data_set_default_bool(settings, "replay2_from_end", replay2_from_end)
obs.obs_data_set_default_bool(settings, "replay3_from_end", replay3_from_end)
def script_description():
return "Adds 3 \"additional\" replay buffers by saving the normal replay buffer clip and cutting out time from the beginning or the end.<br/>" +\
"The times entered should be lower than the current replay buffer time.<br/>" +\
"When you leave the save path empty, the path of the orginial replay is used and the seconds are attached at the end." + \
"<hr/>"
def script_properties():
global debug_mode
if debug_mode: print("[AR] Loaded properties.")
props = obs.obs_properties_create()
if not check_package("moviepy"):
obs.obs_properties_add_button(props, "install_libs", "installs moviepy with pip", install_needed)
obs.obs_properties_add_bool(props, "enabled", "Enabled")
obs.obs_properties_add_bool(props, "debug_mode", "Debug Mode")
obs.obs_properties_add_int(props, "replay1_seconds", "Replay 1 time (seconds)", 1, 600, 1 )
obs.obs_properties_add_path(props, "replay1_path", "Replay 1 save path", obs.OBS_PATH_DIRECTORY, "", None )
obs.obs_properties_add_bool(props, "replay1_remove", "Remove original replay?")
obs.obs_properties_add_bool(props, "replay1_from_end", "Cut time from end instead of beginning?")
obs.obs_properties_add_int(props, "replay2_seconds", "Replay 2 time (seconds)", 1, 600, 1 )
obs.obs_properties_add_path(props, "replay2_path", "Replay 1 save path", obs.OBS_PATH_DIRECTORY, "", None )
obs.obs_properties_add_bool(props, "replay2_remove", "Remove original replay?")
obs.obs_properties_add_bool(props, "replay2_from_end", "Cut time from end instead of begin?")
obs.obs_properties_add_int(props, "replay3_seconds", "Replay 3 time (seconds)", 1, 600, 1 )
obs.obs_properties_add_path(props, "replay3_path", "Replay 3 save path", obs.OBS_PATH_DIRECTORY, "", None )
obs.obs_properties_add_bool(props, "replay3_remove", "Remove original replay?")
obs.obs_properties_add_bool(props, "replay3_from_end", "Cut time from end instead of begin?")
return props
def script_save(settings):
global debug_mode
if debug_mode: print("[AR] Saved properties.")
script_update(settings)
def script_load(settings):
global debug_mode
global replay1_hotkey
global replay2_hotkey
global replay3_hotkey
if debug_mode: print("[AR] Loaded script .")
replay1_hotkey = obs.obs_hotkey_register_frontend("additional_replays.replay1", "Replay 1", save_replay1)
hotkey_save_array = obs.obs_data_get_array(settings, "additional_replays.replay1")
obs.obs_hotkey_load(replay1_hotkey, hotkey_save_array)
obs.obs_data_array_release(hotkey_save_array)
replay2_hotkey = obs.obs_hotkey_register_frontend("additional_replays.replay2", "Replay 2", save_replay2)
hotkey_save_array = obs.obs_data_get_array(settings, "additional_replays.replay2")
obs.obs_hotkey_load(replay2_hotkey, hotkey_save_array)
obs.obs_data_array_release(hotkey_save_array)
replay3_hotkey = obs.obs_hotkey_register_frontend("additional_replays.replay3", "Replay 3", save_replay3)
hotkey_save_array = obs.obs_data_get_array(settings, "additional_replays.replay3")
obs.obs_hotkey_load(replay3_hotkey, hotkey_save_array)
obs.obs_data_array_release(hotkey_save_array)
script_update(settings)
def script_unload():
global debug_mode
if debug_mode: print("[AR] Unloaded script.")
obs.obs_hotkey_unregister(save_replay1)
def script_update(settings):
global debug_mode
if debug_mode: print("[AR] Updated properties.")
global enabled
global replay1_path
global replay1_remove
global replay1_from_end
global replay1_seconds
global replay2_path
global replay2_remove
global replay2_from_end
global replay2_seconds
global replay3_path
global replay3_remove
global replay3_from_end
global replay3_seconds
debug_mode = obs.obs_data_get_bool(settings, "debug_mode")
enabled = obs.obs_data_get_bool(settings, "enabled")
replay1_path = obs.obs_data_get_string(settings, "replay1_path")
replay1_remove = obs.obs_data_get_bool(settings, "replay1_remove")
replay1_from_end = obs.obs_data_get_bool(settings, "replay1_from_end")
replay1_seconds = obs.obs_data_get_int(settings, "replay1_seconds")
hotkey_save_array = obs.obs_hotkey_save(replay1_hotkey)
obs.obs_data_set_array(settings, "additional_replays.replay1", hotkey_save_array)
obs.obs_data_array_release(hotkey_save_array)
replay2_path = obs.obs_data_get_string(settings, "replay2_path")
replay2_remove = obs.obs_data_get_bool(settings, "replay2_remove")
replay2_from_end = obs.obs_data_get_bool(settings, "replay2_from_end")
replay2_seconds = obs.obs_data_get_int(settings, "replay2_seconds")
hotkey_save_array = obs.obs_hotkey_save(replay2_hotkey)
obs.obs_data_set_array(settings, "additional_replays.replay2", hotkey_save_array)
obs.obs_data_array_release(hotkey_save_array)
replay3_path = obs.obs_data_get_string(settings, "replay3_path")
replay3_remove = obs.obs_data_get_bool(settings, "replay3_remove")
replay3_from_end = obs.obs_data_get_bool(settings, "replay3_from_end")
replay3_seconds = obs.obs_data_get_int(settings, "replay3_seconds")
hotkey_save_array = obs.obs_hotkey_save(replay3_hotkey)
obs.obs_data_set_array(settings, "additional_replays.replay3", hotkey_save_array)
obs.obs_data_array_release(hotkey_save_array)
但是,当热键执行脚本时,日志显示:
[AdditionalReplays.py] [AR] save_replay
[AdditionalReplays.py] [AR] seconds=60
[AdditionalReplays.py] [AR] path=R:/
[AdditionalReplays.py] [AR] remove=True
[AdditionalReplays.py] [AR] from_end=False
[AdditionalReplays.py] Traceback (most recent call last):
[AdditionalReplays.py] File "C:/Program Files/obs-studio/data/obs-plugins/frontend-tools/scripts\AdditionalReplays.py", line 136, in save_replay1
[AdditionalReplays.py] save_replay(replay1_seconds, replay1_path, replay1_remove, replay1_from_end)
[AdditionalReplays.py] File "C:/Program Files/obs-studio/data/obs-plugins/frontend-tools/scripts\AdditionalReplays.py", line 168, in save_replay
[AdditionalReplays.py] last_replay = save_and_get_last_replay()
[AdditionalReplays.py] File "C:/Program Files/obs-studio/data/obs-plugins/frontend-tools/scripts\AdditionalReplays.py", line 110, in save_and_get_last_replay
[AdditionalReplays.py] file_timestamp = os.path.getctime(path)
[AdditionalReplays.py] File "C:/Users/chris/AppData/Local/Programs/Python/Python36\lib\genericpath.py", line 65, in getctime
[AdditionalReplays.py] return os.stat(filename).st_ctime
[AdditionalReplays.py] TypeError: stat: path should be string, bytes, os.PathLike or integer, not NoneType
有人知道如何修复这个错误吗?我一直在OBS论坛页面上提问,但没有得到任何人的回答,我自己也有一点Python知识,但还没有解决这个问题
目前没有回答
相关问题 更多 >
编程相关推荐