Compare commits

...

3 commits

Author SHA1 Message Date
j
eb49a320d1 disable original transparancy for now 2023-10-31 09:01:04 +01:00
j
0d554bda05 player 2023-10-30 20:40:25 +01:00
j
b09b7f14d4 formating 2023-10-30 20:25:46 +01:00
5 changed files with 225 additions and 2 deletions

8
player/play-back.desktop Normal file
View file

@ -0,0 +1,8 @@
[Desktop Entry]
Type=Application
Exec=/srv/pandora/t_for_time/player/player.py --mode main --playlist /srv/t_for_time/render/back.m3u
Hidden=false
NoDisplay=false
X-GNOME-Autostart-enabled=true
Name=t-for-time
Comment=

View file

@ -0,0 +1,8 @@
[Desktop Entry]
Type=Application
Exec=/srv/pandora/t_for_time/player/player.py --mode peer --playlist /srv/t_for_time/render/front.m3u
Hidden=false
NoDisplay=false
X-GNOME-Autostart-enabled=true
Name=t-for-time
Comment=

197
player/player.py Executable file
View file

@ -0,0 +1,197 @@
#!/usr/bin/python3
import argparse
import os
import socket
import collections
import time
from threading import Thread
import mpv
import logging
logger = logging.getLogger('t_for_time')
SYNC_TOLERANCE = 0.05
SYNC_GRACE_TIME = 5
SYNC_JUMP_AHEAD = 1
PORT = 9067
DEBUG = False
def mpv_log(loglevel, component, message):
logger.info('[{}] {}: {}'.format(loglevel, component, message))
class Main:
playlist_current_pos = -1
time_pos = -1
class Sync(Thread):
active = True
is_main = True
ready = False
destination = "255.255.255.255"
def __init__(self, *args, **kwargs):
self.is_main = kwargs.get('mode', 'main') == 'main'
self.sock = self.init_socket()
self.main = Main()
if self.is_main:
self.socket_enable_broadcast()
font_size = 28
font = 'Menlo'
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,
)
self.mpv.observe_property('time-pos', self.time_pos_cb)
self.mpv.fullscreen = kwargs.get('fullscreen', False)
self.mpv.loop = 'inf'
self.mpv.loop_file = 'no'
self.mpv.register_key_binding('q', self.q_binding)
self.playlist = kwargs['playlist']
print(self.playlist)
self.mpv.loadlist(self.playlist)
self.deviations = collections.deque(maxlen=10)
if not self.is_main:
self.mpv.pause = False
time.sleep(0.1)
self.mpv.pause = True
self.sync_to_main()
self.ready = True
Thread.__init__(self)
self.daemon = True
self.start()
def run(self):
while self.active:
if self.is_main:
pass
else:
self.read_position_main()
#self.adjust_position()
def q_binding(self, *args):
self.stop()
self.mpv.stop()
def stop(self, *args):
self.active = False
if self.sock:
self.sock.close()
self.sock = None
def time_pos_cb(self, pos, *args, **kwargs):
if self.is_main:
self.send_position_local()
elif self.ready:
self.adjust_position()
def init_socket(self):
sock = socket.socket(socket.AF_INET, socket.SOCK_DGRAM, 0)
sock.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1)
sock.bind(("0.0.0.0", PORT))
return sock
#
# main specific
#
def socket_enable_broadcast(self):
self.sock.setsockopt(socket.SOL_SOCKET, socket.SO_BROADCAST, 1)
self.sock.connect((self.destination, PORT))
def send_position_local(self):
if not self.active:
return
try:
msg = (
"%0.4f %s"
% (self.mpv.time_pos, self.mpv.playlist_current_pos)
).encode()
except:
return
try:
self.sock.send(msg)
except socket.error as e:
logger.error("send failed: %s", e)
#
# follower specific
#
def read_position_main(self):
data = self.sock.recvfrom(1024)[0].decode().split(" ", 1)
self.main.time_pos = float(data[0])
self.main.playlist_current_pos = int(data[1])
def adjust_position(self):
if self.mpv.time_pos is not None:
deviation = self.main.time_pos - self.mpv.time_pos
self.deviations.append(deviation)
median_deviation = self.median(list(self.deviations))
frames = deviation / 0.04
median_frames = median_deviation / 0.04
if time.time() - self.last_sync > SYNC_GRACE_TIME and abs(median_deviation) > SYNC_TOLERANCE:
print('need to sync %0.05f (%d) median %0.05f (%d)' % (deviation, frames, median_deviation, median_frames))
self.sync_to_main()
def median(self, lst):
quotient, remainder = divmod(len(lst), 2)
if remainder:
return sorted(lst)[quotient]
return float(sum(sorted(lst)[quotient - 1:quotient + 1]) / 2.0)
def sync_to_main(self):
self.read_position_main()
#print(self.main.playlist_current_pos)
if self.main.playlist_current_pos != self.mpv.playlist_current_pos:
self.mpv.playlist_play_index(self.main.playlist_current_pos)
self.mpv.pause = False
time.sleep(0.1)
self.mpv.pause = True
pos = self.main.time_pos + SYNC_JUMP_AHEAD
#print(pos, self.mpv.playlist_current_pos, self.mpv.time_pos)
self.mpv.seek(pos, 'absolute', 'exact')
time.sleep(0.1)
self.read_position_main()
sync_timer = time.time() # - 10 * 0.04
deviation = self.main.time_pos - self.mpv.time_pos
while self.active:
#print(deviation, abs(deviation) - (time.time() - sync_timer))
if abs(deviation) - (time.time() - sync_timer) < 0:
self.mpv.pause = False
break
self.last_sync = time.time()
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('--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)
parser.add_argument('--debug', action='store_true', help='debug', default=False)
args = parser.parse_args()
DEBUG = args.debug
if DEBUG:
log_format = '%(asctime)s:%(levelname)s:%(name)s:%(message)s'
logging.basicConfig(level=logging.DEBUG, format=log_format)
base = os.path.dirname(os.path.abspath(__file__))
#os.chdir(base)
player = Sync(mode=args.mode, playlist=args.playlist, fullscreen=not args.window)
while player.active:
player.mpv.wait_for_playback()
player.stop()
del player.mpv
if __name__ == "__main__":
main()

View file

@ -0,0 +1,8 @@
[Desktop Entry]
Type=Application
Exec=/usr/bin/mpv --quiet --loop /srv/t_for_time/render/Saxophone-5.1.mp4
Hidden=false
NoDisplay=false
X-GNOME-Autostart-enabled=true
Name=loop
Comment=

View file

@ -77,6 +77,7 @@ def compose(clips, target=150, base=1024, voice_over=None):
vo2 = vo_keys.pop(chance(seq, len(vo_keys)))
voice_overs.append(voice_over[vo1])
if voice_over[vo1]["duration"] + voice_over[vo2]["duration"] < target:
print("adding second vo")
voice_overs.append(voice_over[vo2])
vo_min = sum([vo['duration'] for vo in voice_overs])
if vo_min > target:
@ -154,7 +155,8 @@ def compose(clips, target=150, base=1024, voice_over=None):
else:
transparency_back = transparency
transparency_front = 0
transparency_original = seq() / 10
#transparency_original = seq() / 10
transparency_original = 1
if "background" in clip:
scene['front']['V1'].append({
'duration': clip['duration'],
@ -207,7 +209,7 @@ def compose(clips, target=150, base=1024, voice_over=None):
'duration': clip['duration'],
'src': foley,
})
print("scene duration %0.3f (target: %0.3f)" % (length, target))
print("scene duration %0.3f (target: %0.3f, vo_min: %0.3f)" % (length, target, vo_min))
return scene
def get_scene_duration(scene):