-
Notifications
You must be signed in to change notification settings - Fork 0
/
OBSAutoReplay.py
171 lines (137 loc) · 5.94 KB
/
OBSAutoReplay.py
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
import obspython as obs
import re
import os
import psutil
import win32api
import win32gui
import win32process
from windows_toasts import Toast, WindowsToaster, ToastDuration
def script_description():
return """
Quality of Life features for Replay Buffer, making it similar to applications like Nvidia Shadowplay.
OBSAutoReplay v1.0 by Dyvinia
""".strip()
def script_properties():
props = obs.obs_properties_create()
scene_for_clips = obs.obs_properties_add_list(props, "scene", "Scene For Clipping",
obs.OBS_COMBO_TYPE_LIST,
obs.OBS_COMBO_FORMAT_STRING)
scenes = obs.obs_frontend_get_scene_names()
for scene in scenes:
obs.obs_property_list_add_string(scene_for_clips, scene, scene)
obs.source_list_release(scenes)
obs.obs_properties_add_bool(props, "disabled", "Disable Clipping")
obs.obs_properties_add_bool(props, "disable_notif", "Disable Notification On Save")
return props
toaster = WindowsToaster('OBSAutoReplay')
sett = None
hotkey_id = obs.OBS_INVALID_HOTKEY_ID
def script_load(settings):
obs.obs_frontend_add_event_callback(obs_frontend_callback)
obs.timer_add(auto_replay_buffer, 10000)
global sett
sett = settings
global hotkey_id
hotkey_id = obs.obs_hotkey_register_frontend("query_clipping", "Check If Replay Buffer Is Enabled", query_clipping_hotkey)
the_data_array = obs.obs_data_get_array(settings, "query_clipping")
obs.obs_hotkey_load(hotkey_id, the_data_array)
obs.obs_data_array_release(the_data_array)
def script_save(settings):
the_data_array = obs.obs_hotkey_save(hotkey_id)
obs.obs_data_set_array(settings, "query_clipping", the_data_array)
obs.obs_data_array_release(the_data_array)
def script_unload():
obs.timer_remove(auto_replay_buffer)
toaster.clear_toasts()
def obs_frontend_callback(event):
if event == obs.OBS_FRONTEND_EVENT_REPLAY_BUFFER_SAVED:
path = move_recording()
if not obs.obs_data_get_bool(sett, "disable_notif"):
newToast = Toast()
newToast.text_fields = ['Saved Replay', "Saved in " + path]
newToast.duration = ToastDuration.Short
toaster.clear_toasts()
toaster.show_toast(newToast)
elif event == obs.OBS_FRONTEND_EVENT_REPLAY_BUFFER_STARTED:
newToast = Toast()
newToast.text_fields = ['Started Replay Buffer']
newToast.duration = ToastDuration.Short
toaster.clear_toasts()
toaster.show_toast(newToast)
elif event == obs.OBS_FRONTEND_EVENT_REPLAY_BUFFER_STOPPED:
newToast = Toast()
newToast.text_fields = ['Stopped Replay Buffer']
newToast.duration = ToastDuration.Short
toaster.clear_toasts()
toaster.show_toast(newToast)
def auto_replay_buffer():
if obs.obs_data_get_bool(sett, "disabled"):
if obs.obs_frontend_replay_buffer_active():
obs.obs_frontend_replay_buffer_stop()
return
scene_as_source = obs.obs_frontend_get_current_scene()
if obs.obs_source_get_name(scene_as_source) != obs.obs_data_get_string(sett, "scene"):
obs.obs_source_release(scene_as_source)
return
scene_items = obs.obs_scene_enum_items(obs.obs_scene_from_source(scene_as_source))
source = None
for item in scene_items:
source_item = obs.obs_sceneitem_get_source(item)
source_id = obs.obs_source_get_id(source_item)
if source_id == "game_capture":
source = source_item
obs.sceneitem_list_release(scene_items)
if source is None:
print("Could not find Game Capture source in current scene")
if (not obs.obs_frontend_replay_buffer_active() and obs.obs_source_get_width(source) > 0):
obs.obs_frontend_replay_buffer_start()
elif (obs.obs_frontend_replay_buffer_active() and obs.obs_source_get_width(source) == 0):
obs.obs_frontend_replay_buffer_stop()
obs.obs_source_release(scene_as_source)
def move_recording():
replay_buffer = obs.obs_frontend_get_replay_buffer_output()
cd = obs.calldata_create()
ph = obs.obs_output_get_proc_handler(replay_buffer)
obs.proc_handler_call(ph, "get_last_replay", cd)
path = obs.calldata_string(cd, "path")
obs.calldata_destroy(cd)
obs.obs_output_release(replay_buffer)
game = get_foreground_window()
new_path = os.path.dirname(path) + '/Replays/' + game + '/' + os.path.basename(path)
print("Saving replay to: " + new_path)
os.renames(path, new_path)
return '/Replays/' + game + '/'
def get_foreground_window():
try:
hwnd = win32gui.GetForegroundWindow()
_, pid = win32process.GetWindowThreadProcessId(hwnd)
exe = psutil.Process(pid).exe()
print(exe)
try:
language, codepage = win32api.GetFileVersionInfo(exe, '\\VarFileInfo\\Translation')[0]
stringFileInfo = u'\\StringFileInfo\\%04X%04X\\%s' % (language, codepage, "FileDescription")
return alphanumeric(win32api.GetFileVersionInfo(exe, stringFileInfo))
except:
return psutil.Process(pid).name().replace(".exe", "").replace('.', '').strip()
except:
return "Other"
def alphanumeric(s):
fixed = re.sub(r'[^A-Za-z0-9 ]+', '', s).strip()
if len(fixed) > 0:
return fixed
else:
return "Other"
def query_clipping_hotkey(is_pressed):
toasterQuery = WindowsToaster('OBSAutoReplay')
if is_pressed and obs.obs_frontend_replay_buffer_active():
newToast = Toast()
newToast.text_fields = ['Replay Buffer is Currently Active']
newToast.duration = ToastDuration.Short
toasterQuery.clear_toasts()
toasterQuery.show_toast(newToast)
elif is_pressed and not obs.obs_frontend_replay_buffer_active():
newToast = Toast()
newToast.text_fields = ['Replay Buffer is Not Active']
newToast.duration = ToastDuration.Short
toasterQuery.clear_toasts()
toasterQuery.show_toast(newToast)