Compare commits
No commits in common. "01f669b61d77dfaaf84377a691bb2a24fe282edd" and "582bcf1813d02f935745607d10a70b00c62385ca" have entirely different histories.
01f669b61d
...
582bcf1813
4 changed files with 10 additions and 156 deletions
|
@ -1,15 +0,0 @@
|
||||||
[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
|
|
|
@ -1,19 +0,0 @@
|
||||||
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)
|
|
|
@ -1,9 +1,8 @@
|
||||||
#!/usr/bin/python3
|
#!/usr/bin/python3
|
||||||
import argparse
|
import argparse
|
||||||
import collections
|
|
||||||
import json
|
|
||||||
import os
|
import os
|
||||||
import socket
|
import socket
|
||||||
|
import collections
|
||||||
import time
|
import time
|
||||||
from threading import Thread
|
from threading import Thread
|
||||||
from datetime import datetime
|
from datetime import datetime
|
||||||
|
@ -58,15 +57,6 @@ class Sync(Thread):
|
||||||
if self.is_main:
|
if self.is_main:
|
||||||
self.socket_enable_broadcast()
|
self.socket_enable_broadcast()
|
||||||
|
|
||||||
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(
|
self.mpv = mpv.MPV(
|
||||||
log_handler=mpv_log, input_default_bindings=True,
|
log_handler=mpv_log, input_default_bindings=True,
|
||||||
input_vo_keyboard=True,
|
input_vo_keyboard=True,
|
||||||
|
@ -83,7 +73,6 @@ class Sync(Thread):
|
||||||
self.playlist_mtime = os.stat(self.playlist).st_mtime
|
self.playlist_mtime = os.stat(self.playlist).st_mtime
|
||||||
self.mpv.loadlist(self.playlist)
|
self.mpv.loadlist(self.playlist)
|
||||||
logger.error("loaded paylist: %s", 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)
|
self.deviations = collections.deque(maxlen=10)
|
||||||
if not self.is_main:
|
if not self.is_main:
|
||||||
self.mpv.pause = False
|
self.mpv.pause = False
|
||||||
|
@ -146,33 +135,8 @@ class Sync(Thread):
|
||||||
playlist_mtime = os.stat(self.playlist).st_mtime
|
playlist_mtime = os.stat(self.playlist).st_mtime
|
||||||
if self.playlist_mtime != playlist_mtime:
|
if self.playlist_mtime != playlist_mtime:
|
||||||
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.error("reloaded paylist: %s", self.playlist)
|
||||||
logger.debug("current playlist: %s", json.dumps(self.mpv.playlist, indent=2))
|
|
||||||
|
|
||||||
def init_socket(self):
|
def init_socket(self):
|
||||||
sock = socket.socket(socket.AF_INET, socket.SOCK_DGRAM, 0)
|
sock = socket.socket(socket.AF_INET, socket.SOCK_DGRAM, 0)
|
||||||
|
@ -297,7 +261,7 @@ def main():
|
||||||
prefix = os.path.expanduser('~/Videos/t_for_time')
|
prefix = os.path.expanduser('~/Videos/t_for_time')
|
||||||
|
|
||||||
parser = argparse.ArgumentParser(description='t_for_time sync player')
|
parser = argparse.ArgumentParser(description='t_for_time sync player')
|
||||||
parser.add_argument('--mode', help='peer or main', default="peer")
|
parser.add_argument('--mode', help='ip of peer', default="peer")
|
||||||
parser.add_argument('--playlist', default='/srv/t_for_time/render/128/front.m3u', help="m3u")
|
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('--prefix', help='video location', default=prefix)
|
||||||
parser.add_argument('--window', action='store_true', help='run in window', default=False)
|
parser.add_argument('--window', action='store_true', help='run in window', default=False)
|
||||||
|
|
76
render.py
76
render.py
|
@ -1,6 +1,5 @@
|
||||||
#!/usr/bin/python3
|
#!/usr/bin/python3
|
||||||
from collections import defaultdict
|
from collections import defaultdict
|
||||||
from glob import glob
|
|
||||||
import json
|
import json
|
||||||
import os
|
import os
|
||||||
import re
|
import re
|
||||||
|
@ -308,16 +307,6 @@ def get_scene_duration(scene):
|
||||||
duration += clip['duration']
|
duration += clip['duration']
|
||||||
return 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=''):
|
def render(root, scene, prefix=''):
|
||||||
fps = 24
|
fps = 24
|
||||||
files = []
|
files = []
|
||||||
|
@ -620,68 +609,3 @@ def update_subtitles(options):
|
||||||
srt = ox.srt.encode(subs)
|
srt = ox.srt.encode(subs)
|
||||||
write_if_new(str(path), srt, 'b')
|
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)
|
|
||||||
|
|
Loading…
Reference in a new issue