Compare commits

...

4 Commits

Author SHA1 Message Date
j 01f669b61d better way to calculate remove 2024-03-19 11:48:36 +01:00
j a229194d48 actually cleanup, only remove renders in infinity range 2024-03-19 10:12:15 +01:00
j 3d5293e7de lower priority 2024-03-19 10:11:40 +01:00
j 6e4e8ca7a6 to infinity 2024-03-10 18:14:59 +00:00
4 changed files with 156 additions and 10 deletions

View File

@ -0,0 +1,15 @@
[Unit]
Description=render to infinity and beyond
After=pandora.service
[Service]
Type=simple
Restart=always
User=pandora
Group=pandora
Nice=19
WorkingDirectory=/srv/pandora/pandora
ExecStart=/srv/pandora/pandora/manage.py infinity
[Install]
WantedBy=multi-user.target

View File

@ -0,0 +1,19 @@
import json
import os
import subprocess
from django.core.management.base import BaseCommand
from django.conf import settings
from ...render import render_infinity
class Command(BaseCommand):
help = 'render infinity'
def add_arguments(self, parser):
parser.add_argument('--prefix', action='store', dest='prefix', default="/srv/t_for_time", help='prefix to build clips in')
parser.add_argument('--duration', action='store', dest='duration', default="3600", help='target duration of all fragments in seconds')
def handle(self, **options):
render_infinity(options)

View File

@ -1,8 +1,9 @@
#!/usr/bin/python3
import argparse
import collections
import json
import os
import socket
import collections
import time
from threading import Thread
from datetime import datetime
@ -57,13 +58,22 @@ class Sync(Thread):
if self.is_main:
self.socket_enable_broadcast()
self.mpv = mpv.MPV(
log_handler=mpv_log, input_default_bindings=True,
input_vo_keyboard=True,
sub_text_font_size=FONT_SIZE, sub_text_font=FONT,
sub_border_size=FONT_BORDER,
sub_margin_y=SUB_MARGIN,
)
if mpv.MPV_VERSION >= (2, 2):
self.mpv = mpv.MPV(
log_handler=mpv_log, input_default_bindings=True,
input_vo_keyboard=True,
sub_font_size=FONT_SIZE, sub_font=FONT,
sub_border_size=FONT_BORDER,
sub_margin_y=SUB_MARGIN,
)
else:
self.mpv = mpv.MPV(
log_handler=mpv_log, input_default_bindings=True,
input_vo_keyboard=True,
sub_text_font_size=FONT_SIZE, sub_text_font=FONT,
sub_border_size=FONT_BORDER,
sub_margin_y=SUB_MARGIN,
)
self.mpv.observe_property('time-pos', self.time_pos_cb)
self.mpv.fullscreen = kwargs.get('fullscreen', False)
self.mpv.loop_file = False
@ -73,6 +83,7 @@ class Sync(Thread):
self.playlist_mtime = os.stat(self.playlist).st_mtime
self.mpv.loadlist(self.playlist)
logger.error("loaded paylist: %s", self.playlist)
logger.debug("current playlist: %s", json.dumps(self.mpv.playlist, indent=2))
self.deviations = collections.deque(maxlen=10)
if not self.is_main:
self.mpv.pause = False
@ -135,8 +146,33 @@ class Sync(Thread):
playlist_mtime = os.stat(self.playlist).st_mtime
if self.playlist_mtime != playlist_mtime:
self.playlist_mtime = playlist_mtime
self.mpv.loadlist(self.playlist)
#self.mpv.loadlist(self.playlist)
with open(self.playlist) as fd:
items = fd.read().strip().split('\n')
base = os.path.dirname(self.playlist)
items = [os.path.join(base, item) for item in items]
current_items = self.mpv.playlist_filenames
for filename in items:
if filename not in current_items:
self.mpv.playlist_append(filename)
logger.error("add: %s", filename)
remove = []
for filename in current_items:
if filename not in items:
remove.append(filename)
for filename in remove:
for idx, item in enumerate(self.mpv.playlist):
if item["filename"] == filename:
logger.error("remove: %s %s", idx, filename)
self.mpv.playlist_remove(idx)
break
for idx, filename in enumerate(items):
current_idx = self.mpv.playlist_filenames.index(filename)
if idx != current_idx:
logger.error("move item %s %s -> %s", filename, current_idx, idx)
self.mpv.playlist_move(current_idx, idx)
logger.error("reloaded paylist: %s", self.playlist)
logger.debug("current playlist: %s", json.dumps(self.mpv.playlist, indent=2))
def init_socket(self):
sock = socket.socket(socket.AF_INET, socket.SOCK_DGRAM, 0)
@ -261,7 +297,7 @@ def main():
prefix = os.path.expanduser('~/Videos/t_for_time')
parser = argparse.ArgumentParser(description='t_for_time sync player')
parser.add_argument('--mode', help='ip of peer', default="peer")
parser.add_argument('--mode', help='peer or main', default="peer")
parser.add_argument('--playlist', default='/srv/t_for_time/render/128/front.m3u', help="m3u")
parser.add_argument('--prefix', help='video location', default=prefix)
parser.add_argument('--window', action='store_true', help='run in window', default=False)

View File

@ -1,5 +1,6 @@
#!/usr/bin/python3
from collections import defaultdict
from glob import glob
import json
import os
import re
@ -307,6 +308,16 @@ def get_scene_duration(scene):
duration += clip['duration']
return duration
def get_offset_duration(prefix):
duration = 0
for root, folders, files in os.walk(prefix):
for f in files:
if f == 'scene.json':
path = os.path.join(root, f)
scene = json.load(open(path))
duration += get_scene_duration(scene)
return duration
def render(root, scene, prefix=''):
fps = 24
files = []
@ -609,3 +620,68 @@ def update_subtitles(options):
srt = ox.srt.encode(subs)
write_if_new(str(path), srt, 'b')
def update_m3u(render_prefix, exclude=[]):
files = ox.sorted_strings(glob(render_prefix + "*/*/back.mp4"))
for ex in exclude:
files = [f for f in files if not f.startswith(ex + "/")]
back_m3u = "\n".join(files)
back_m3u = back_m3u.replace(render_prefix, "")
front_m3u = back_m3u.replace("back.mp4", "front.mp4")
back_m3u_f = render_prefix + "back.m3u"
front_m3u_f = render_prefix + "front.m3u"
with open(back_m3u_f + "_", "w") as fd:
fd.write(back_m3u)
with open(front_m3u_f + "_", "w") as fd:
fd.write(front_m3u)
shutil.move(front_m3u_f + "_", front_m3u_f)
cmd = ["scp", front_m3u_f, "front:" + front_m3u_f]
subprocess.check_call(cmd)
shutil.move(back_m3u_f + "_", back_m3u_f)
def render_infinity(options):
prefix = options['prefix']
duration = int(options['duration'])
state_f = os.path.join(prefix, "infinity.json")
if os.path.exists(state_f):
with open(state_f) as fd:
state = json.load(fd)
else:
state = {
"offset": 100,
"max-items": 30,
"no_video": False,
}
for key in ("prefix", "duration"):
state[key] = options[key]
while True:
render_prefix = state["prefix"] + "/render/"
current = [
f for f in os.listdir(render_prefix)
if f.isdigit() and os.path.isdir(render_prefix + f) and state["offset"] > int(f) >= 100
]
if len(current) > state["max-items"]:
current = ox.sorted_strings(current)
remove = current[:-state["max-items"]]
update_m3u(render_prefix, exclude=remove)
for folder in remove:
folder = render_prefix + folder
print("remove", folder)
shutil.rmtree(folder)
cmd = ["ssh", "front", "rm", "-rf", folder]
#print(cmd)
subprocess.check_call(cmd)
render_all(state)
path = "%s%s/" % (render_prefix, state["offset"])
cmd = ['rsync', '-a', path, "front:" + path]
subprocess.check_call(cmd)
update_m3u(render_prefix)
state["offset"] += 1
with open(state_f + "~", "w") as fd:
json.dump(state, fd, indent=2)
shutil.move(state_f + "~", state_f)