Initial commit
This commit is contained in:
4
.gitignore
vendored
Normal file
4
.gitignore
vendored
Normal file
@@ -0,0 +1,4 @@
|
|||||||
|
config.toml
|
||||||
|
.venv
|
||||||
|
*.mp4
|
||||||
|
__pycache__/
|
||||||
28
clip.py
Normal file
28
clip.py
Normal file
@@ -0,0 +1,28 @@
|
|||||||
|
from datetime import datetime
|
||||||
|
from video import clip
|
||||||
|
|
||||||
|
import obsws_python as obs
|
||||||
|
import sys, os
|
||||||
|
|
||||||
|
command = sys.argv[1] if len(sys.argv) > 1 else None
|
||||||
|
|
||||||
|
con = obs.ReqClient()
|
||||||
|
response = con.get_version()
|
||||||
|
print(f"OBS WebSocket Version: {response.obs_web_socket_version}")
|
||||||
|
|
||||||
|
if command == "start":
|
||||||
|
con.start_record()
|
||||||
|
print(f"Started recording")
|
||||||
|
elif command == "stop":
|
||||||
|
con.stop_record()
|
||||||
|
print("Stopped recording")
|
||||||
|
elif command == "clip":
|
||||||
|
record_dir = con.get_record_directory()
|
||||||
|
output_file_name = f"{datetime.now().strftime("%Y-%m-%d %H:%M:%S")}.mp4"
|
||||||
|
clip(record_dir.record_directory, output_file_name)
|
||||||
|
|
||||||
|
print(f"Created clip: {output_file_name}")
|
||||||
|
else:
|
||||||
|
print("Unknown command. Use 'start', 'stop', or 'clip'.")
|
||||||
|
|
||||||
|
con.disconnect()
|
||||||
4
example.config.toml
Normal file
4
example.config.toml
Normal file
@@ -0,0 +1,4 @@
|
|||||||
|
[connection]
|
||||||
|
host = "localhost"
|
||||||
|
port = 4455
|
||||||
|
password = "6BQWrpHLbyJxNLPJ"
|
||||||
7
readme.md
Normal file
7
readme.md
Normal file
@@ -0,0 +1,7 @@
|
|||||||
|
A minimal Python script to control OBS Studio recording via OBS WebSocket and to combine segmented .ts recordings into a single .mp4 clip using FFmpeg.
|
||||||
|
|
||||||
|
This project is meant to be (and will evolve into) a long-duration, disk-backed replay buffer.
|
||||||
|
|
||||||
|
# Steps
|
||||||
|
1) Setup OBS and make the recording output: "ts" with a 1 minute segment size
|
||||||
|
1) Setup config.toml with host, port, password info
|
||||||
28
video.py
Normal file
28
video.py
Normal file
@@ -0,0 +1,28 @@
|
|||||||
|
import os, subprocess, datetime
|
||||||
|
|
||||||
|
def combine_ts_to_mp4(ts_files, output_file):
|
||||||
|
# FFMPEG requires a text file with the list of files to concatenate
|
||||||
|
with open("file_list.txt", "w") as f:
|
||||||
|
for ts in ts_files:
|
||||||
|
f.write(f"file '{ts}'\n")
|
||||||
|
|
||||||
|
subprocess.run(["ffmpeg", "-y", "-f", "concat", "-safe", "0", "-i", "file_list.txt", "-c", "copy", output_file])
|
||||||
|
os.remove("file_list.txt")
|
||||||
|
|
||||||
|
def clean_old_ts_files(record_dir, max_age_seconds=60*60*3):
|
||||||
|
current_time = datetime.datetime.now().timestamp()
|
||||||
|
for filename in os.listdir(record_dir):
|
||||||
|
if filename.endswith(".ts"):
|
||||||
|
file_path = os.path.join(record_dir, filename)
|
||||||
|
file_age = current_time - os.path.getmtime(file_path)
|
||||||
|
if file_age > max_age_seconds:
|
||||||
|
os.remove(file_path)
|
||||||
|
print(f"Deleted old file: {file_path}")
|
||||||
|
|
||||||
|
def clip(record_dir, output_file_name):
|
||||||
|
# Gather all ts files and combine them into a single mp4
|
||||||
|
ts_files = [f for f in os.listdir(record_dir) if f.endswith(".ts")]
|
||||||
|
ts_files.sort(key=lambda x: os.path.getmtime(os.path.join(record_dir, x)))
|
||||||
|
|
||||||
|
combine_ts_to_mp4([os.path.join(record_dir, f) for f in ts_files], output_file_name)
|
||||||
|
clean_old_ts_files(record_dir)
|
||||||
Reference in New Issue
Block a user