diff --git a/bin/vidref b/bin/vidref --- a/bin/vidref +++ b/bin/vidref @@ -16,19 +16,20 @@ light9/web/light9-vidref-playback.js Lit """ from run_local import log -from twisted.internet import reactor, defer - +from typing import cast import logging, optparse, json, base64, os, glob -import cyclone.web, cyclone.httpclient, cyclone.websocket -from light9 import networking, showconfig -from light9.vidref import videorecorder -from rdflib import URIRef -from light9.newtypes import Song -from rdfdb.syncedgraph import SyncedGraph -from cycloneerr import PrettyErrorHandler -from typing import cast + from greplin import scales from greplin.scales.cyclonehandler import StatsHandler +from rdflib import URIRef +from twisted.internet import reactor, defer +import cyclone.web, cyclone.httpclient, cyclone.websocket + +from cycloneerr import PrettyErrorHandler +from light9 import networking, showconfig +from light9.newtypes import Song +from light9.vidref import videorecorder +from rdfdb.syncedgraph import SyncedGraph parser = optparse.OptionParser() parser.add_option("-v", "--verbose", action="store_true", help="logging.DEBUG") @@ -40,9 +41,9 @@ stats = scales.collection( '/webServer', scales.RecentFpsStat('liveWebsocketFrameFps'), scales.IntStat('liveClients'), - ) - + + class Snapshot(cyclone.web.RequestHandler): @defer.inlineCallbacks @@ -108,20 +109,20 @@ class Time(cyclone.web.RequestHandler): self.set_status(202) - class Clips(PrettyErrorHandler, cyclone.web.RequestHandler): def delete(self): clip = URIRef(self.get_argument('uri')) videorecorder.deleteClip(clip) + class ReplayMap(PrettyErrorHandler, cyclone.web.RequestHandler): def get(self): song = Song(self.get_argument('song')) clips = [] - videoPaths = glob.glob(os.path.join(videorecorder.songDir(song), - b'*.mp4')) + videoPaths = glob.glob( + os.path.join(videorecorder.songDir(song), b'*.mp4')) for vid in videoPaths: pts = [] for line in open(vid.replace(b'.mp4', b'.timing'), 'rb'): @@ -175,7 +176,6 @@ reactor.listenTCP( (r'/stats/(.*)', StatsHandler, { 'serverName': 'vidref' }), - ], debug=True, )) diff --git a/light9/vidref/videorecorder.py b/light9/vidref/videorecorder.py --- a/light9/vidref/videorecorder.py +++ b/light9/vidref/videorecorder.py @@ -1,24 +1,24 @@ from dataclasses import dataclass +from io import BytesIO from typing import Optional import time, logging, os, traceback -from io import BytesIO import gi gi.require_version('Gst', '1.0') gi.require_version('GstBase', '1.0') -import PIL.Image from gi.repository import Gst +from greplin import scales +from rdflib import URIRef from rx.subject import BehaviorSubject from twisted.internet import threads -from rdflib import URIRef +import PIL.Image import moviepy.editor import numpy -from greplin import scales +from light9 import showconfig from light9.ascoltami.musictime_client import MusicTime from light9.newtypes import Song -from light9 import showconfig log = logging.getLogger() @@ -30,9 +30,9 @@ stats = scales.collection( scales.PmfStat('crop', recalcPeriod=1), scales.RecentFpsStat('encodeFrameFps'), scales.RecentFpsStat('queueGstFrameFps'), - ) + @dataclass class CaptureFrame: img: PIL.Image @@ -55,6 +55,7 @@ def songDir(song: Song) -> bytes: showconfig.root(), b'video', song.replace('http://', '').replace('/', '_').encode('ascii')) + def takeUri(songPath: bytes) -> URIRef: p = songPath.decode('ascii').split('/') take = p[-1].replace('.mp4', '') @@ -62,17 +63,21 @@ def takeUri(songPath: bytes) -> URIRef: return URIRef('/'.join( ['http://light9.bigasterisk.com/show', song[-2], song[-1], take])) + def deleteClip(uri: URIRef): # uri http://light9.bigasterisk.com/show/dance2019/song6/take_155 # path show/dance2019/video/light9.bigasterisk.com_show_dance2019_song6/take_155.* w = uri.split('/')[-4:] - path = '/'.join([w[0], w[1], 'video', - f'light9.bigasterisk.com_{w[0]}_{w[1]}_{w[2]}', w[3]]) + path = '/'.join([ + w[0], w[1], 'video', f'light9.bigasterisk.com_{w[0]}_{w[1]}_{w[2]}', + w[3] + ]) log.info(f'deleting {uri} {path}') stats.deletes += 1 for fn in [path + '.mp4', path + '.timing']: os.remove(fn) + class FramesToVideoFiles: """ @@ -166,7 +171,6 @@ class FramesToVideoFiles: if self.currentClipFrameCount < 400: log.info('too small- deleting') deleteClip(takeUri(self.outMp4.encode('ascii'))) - def _bg_make_frame(self, video_time_secs): stats.encodeFrameFps.mark() @@ -256,7 +260,7 @@ class GstSource: @stats.crop.time() def crop(self, img): return img.crop((0, 100, 640, 380)) - + def setupPipelineError(self, pipe, cb): bus = pipe.get_bus()