First commit

This commit is contained in:
Fierelier 2021-08-06 14:44:17 +02:00
commit 68a84becdc
4 changed files with 205 additions and 0 deletions

10
ffreplay-linux.ini Normal file
View File

@ -0,0 +1,10 @@
[DEFAULT]
# User config folder
# These settings can override all of the other settings
userConfig=$SYS:HOME$/.config/ffreplay/ffreplay.ini
# Input options
input=["-f","pulse","-i","1","-framerate","30","-f","x11grab","-i",":0.0+0,0"]
# Temporary storage folder. THIS FOLDER WILL BE DELETED. CHOOSE A NON-EXISTANT FOLDER.
temp=/dev/shm/ffreplay-$PID$

10
ffreplay-windows.ini Normal file
View File

@ -0,0 +1,10 @@
[DEFAULT]
# User config folder
# These settings can override all of the other settings
userConfig=$SYS:APPDATA$/ffreplay/ffreplay.ini
# Input options
input=["-f","dshow","-i","audio=virtual-audio-capturer","-f","gdigrab","-framerate","30","-i","desktop"]
# Temporary storage folder. THIS FOLDER WILL BE DELETED. CHOOSE A NON-EXISTANT FOLDER.
temp=$SYS:TEMP$/ffreplay-$PID$

19
ffreplay.ini Normal file
View File

@ -0,0 +1,19 @@
[DEFAULT]
# Binary
# The path to the binary to run for recording
binary=ffmpeg
# Output path
# Where should replays be saved?
outputPath=$SP$/ffreplay-$TIME$
# Segment time
# How long a segment of video is, in seconds
segmentTime=30
# Segment amount
# How many segments should be recorded at maximum. If you want a recording that is 10 minutes at least, and your segment time is 30, you want to set 21 -- 21 * 30 seconds = 630 seconds at maximum, 600 seconds at minimum
segmentCount=21
# Output options, formatted in json
output=["-c:v","libx264","-pix_fmt","yuv420p","-preset","ultrafast","-c:a","aac","-b:a","128k","-bufsize","20M","-maxrate","10M","-f","mpegts","-f","segment","-segment_time","$CONF:DEFAULT/segmentTime$","-segment_wrap","$CONF:DEFAULT/segmentCount$","-segment_list","$CONF:DEFAULT/temp$/segments.ffcat","-segment_list_type","ffconcat","-segment_list_size","$CONF:DEFAULT/segmentCount$","$CONF:DEFAULT/temp$/seg%d.ts"]

166
ffreplay.py Executable file
View File

@ -0,0 +1,166 @@
#!/usr/bin/env python3
import sys
oldexcepthook = sys.excepthook
def newexcepthook(type,value,traceback):
oldexcepthook(type,value,traceback)
input("Press ENTER to quit.")
sys.excepthook = newexcepthook
import os
p = os.path.join
pUp = os.path.dirname
s = False
if getattr(sys, 'frozen', False) and hasattr(sys, '_MEIPASS'):
s = os.path.realpath(sys.executable)
else:
s = os.path.realpath(__file__)
sp = pUp(s)
import platform
import configparser
import subprocess
import json
import shutil
import datetime
import math
print("Grabbing system info...")
pid = os.getpid()
osName = platform.system().lower()
if osName == "darwin": osName = "macos"
def configToDict(conf):
out = {}
for group in conf:
out[group] = {}
for key in conf[group]:
out[group][key] = conf[group][key]
return out
def makeEnvironment(config = False):
print("Creating environment...")
cenv = {}
cenv["SP"] = sp
cenv["OS"] = osName
cenv["PID"] = pid
if config:
for group in config:
for key in config[group]:
value = config[group][key]
path = group+ "/" +key
cenv["CONF:" +path] = value
for env in os.environ:
cenv["SYS:" +env] = os.environ[env]
print(json.dumps(cenv,indent=2))
print("")
return cenv
def applyEnvironment(cenv,config):
print("Applying environment...")
found = True
while found == True:
found = False
for group in config:
for key in config[group]:
value = config[group][key]
for var in cenv:
varStr = "$" +var+ "$"
if varStr in value:
found = True
value = value.replace(varStr,str(cenv[var]))
config[group][key] = value
print(json.dumps(configToDict(config),indent=2))
print("")
def waitForInput():
inp = sys.stdin.read(1)
return
def getTimeString():
now = datetime.datetime.now()
nowl = [
str(now.year),str(now.month),str(now.day),
str(now.hour),str(now.minute),str(now.second),
str(math.floor(now.microsecond / 10000))
]
index = 0
while (index < 7):
value = nowl[index]
if len(value) < 2: nowl[index] = "0" + value
index = index + 1
return "-".join(nowl[0:3]) + "_" + "-".join(nowl[3:6]) + "." +nowl[6]
def main():
# Setup
print("Loading configs...")
configPath = os.path.splitext(s)[0]
configPathOS = configPath + "-" +osName+ ".ini"
if not os.path.isfile(configPathOS):
print("Warning: No OS-specific config found (" +configPathOS+ "), falling back to linux defaults")
configPathOS = configPath + "-linux.ini"
configPath += ".ini"
config = configparser.ConfigParser(interpolation=None)
config.optionxform = str
config.read(configPath)
if os.path.isfile(configPathOS): config.read(configPathOS)
ffrEnv = makeEnvironment(config)
applyEnvironment(ffrEnv,config)
if os.path.isfile(config["DEFAULT"]["userConfig"]):
print("Reading user-specific config...")
config.read(config["DEFAULT"]["userConfig"])
ffrEnv = makeEnvironment(config)
applyEnvironment(ffrEnv,config)
cmdBinary = config["DEFAULT"]["binary"]
cmdInput = json.loads(config["DEFAULT"]["input"])
cmdOutput = json.loads(config["DEFAULT"]["output"])
# Main
if len(sys.argv[1:]) > 0:
if sys.argv[1] in ["c","convert"]:
for arg in sys.argv[2:]:
proc = subprocess.Popen([cmdBinary,"-f","concat","-safe","0","-i",p(arg,"segments.ffcat"),"-c","copy","-map","0","-movflags","+faststart",arg + ".mp4"])
proc.wait()
sys.exit(0)
if os.path.isdir(config["DEFAULT"]["temp"]):
shutil.rmtree(config["DEFAULT"]["temp"])
proc = False
try:
while True:
os.makedirs(config["DEFAULT"]["temp"])
proc = subprocess.Popen(
[cmdBinary] + cmdInput + cmdOutput,
stdin=subprocess.PIPE
)
waitForInput()
timeString = getTimeString()
proc.communicate(input=b'q')
proc.wait()
shutil.copytree(config["DEFAULT"]["temp"],config["DEFAULT"]["outputPath"].replace("$TIME$",timeString))
shutil.rmtree(config["DEFAULT"]["temp"])
except:
try:
proc.communicate(input=b'q')
proc.wait()
except:
pass
try:
shutil.rmtree(config["DEFAULT"]["temp"])
except Exception as e2:
raise e2
raise
main()