@ -3,6 +3,7 @@ import datetime
import logging
import logging
import os
import os
import subprocess
import subprocess
from hashlib import sha256
from urlparse import urlparse
from urlparse import urlparse
from uuid import uuid4
from uuid import uuid4
@ -21,14 +22,16 @@ class RaceNotFound(Exception):
class CantFindStart ( Exception ) :
class CantFindStart ( Exception ) :
def __init__ ( self , racer , found) :
def __init__ ( self , racer , racer_number, found, path ) :
self . racer = racer
self . racer = racer
self . racer_number = racer_number
self . found = found
self . found = found
self . path = path
def __str__ ( self ) :
def __str__ ( self ) :
if self . found > 0 :
if self . found > 0 :
return " Found multiple ( {} ) possible start points for {} " . format ( self . found , self . racer )
return " Found multiple ( {} ) possible start points for racer {} ( {} ) " . format ( self . found , self . racer_number , self . racer )
else :
else :
return " Failed to find start point for {} ". format ( self . racer )
return " Failed to find start point for racer {} ({} ) ". format ( self . racer_number , self . racer )
def ts ( dt ) :
def ts ( dt ) :
@ -77,7 +80,10 @@ def conn_from_url(url):
)
)
def review ( match_id , race_number , base_dir , db_url , start_range = ( 0 , 5 ) , finish_range = ( - 5 , 10 ) ) :
def review (
match_id , race_number , base_dir , db_url , start_range = ( 0 , 5 ) , finish_range = ( - 5 , 10 ) ,
racer1_start = None , racer2_start = None ,
) :
logger = logging . getLogger ( " review " ) . getChild ( " {} - {} " . format ( match_id , race_number ) )
logger = logging . getLogger ( " review " ) . getChild ( " {} - {} " . format ( match_id , race_number ) )
conn = conn_from_url ( db_url )
conn = conn_from_url ( db_url )
@ -111,11 +117,15 @@ def review(match_id, race_number, base_dir, db_url, start_range=(0, 5), finish_r
( racer1 , racer2 , start , duration ) , = data
( racer1 , racer2 , start , duration ) , = data
end = start + datetime . timedelta ( seconds = duration / 100. )
end = start + datetime . timedelta ( seconds = duration / 100. )
# cache hash encapsulates all input args
cache_hash = sha256 ( str ( ( match_id , race_number , start_range , finish_range , racer1_start , racer2_start ) ) )
cache_str = cache_hash . digest ( ) . encode ( ' base64 ' ) [ : 12 ]
output_name = " {} - {} - {} - {} " . format ( match_id , racer1 , racer2 , race_number )
output_name = " {} - {} - {} - {} " . format ( match_id , racer1 , racer2 , race_number )
output_dir = os . path . join ( base_dir , " reviews " , output_name )
output_dir = os . path . join ( base_dir , " reviews " , output_name )
if not os . path . exists ( output_dir ) :
if not os . path . exists ( output_dir ) :
os . makedirs ( output_dir )
os . makedirs ( output_dir )
result_name = " review_ {} _{} .mp4" . format ( * finish_range )
result_name = " review_ {} .mp4" . format ( cache_str )
result_path = os . path . join ( output_dir , result_name )
result_path = os . path . join ( output_dir , result_name )
if os . path . exists ( result_path ) :
if os . path . exists ( result_path ) :
logger . info ( " Result already exists for {} , reusing " . format ( result_path ) )
logger . info ( " Result already exists for {} , reusing " . format ( result_path ) )
@ -123,10 +133,12 @@ def review(match_id, race_number, base_dir, db_url, start_range=(0, 5), finish_r
finish_paths = [ ]
finish_paths = [ ]
for racer_ number, racer in enumerate ( ( racer1 , racer2 ) ) :
for racer_ index, ( racer , time_offset ) in enumerate ( ( ( racer1 , racer1_start ) , ( racer2 , racer2_start ) ) ) :
nonce = str ( uuid4 ( ) )
nonce = str ( uuid4 ( ) )
start_path = os . path . join ( output_dir , " start- {} - {} .mp4 " . format ( racer_number , nonce ) )
racer_number = racer_index + 1
if time_offset is None :
start_path = os . path . join ( output_dir , " start- {} - {} .mp4 " . format ( racer_number , nonce ) )
logger . info ( " Cutting start for racer {} ( {} ) " . format ( racer_number , racer ) )
logger . info ( " Cutting start for racer {} ( {} ) " . format ( racer_number , racer ) )
start_start , start_end = add_range ( start , start_range )
start_start , start_end = add_range ( start , start_range )
cut_to_file ( logger , start_path , base_dir , racer , start_start , start_end )
cut_to_file ( logger , start_path , base_dir , racer , start_start , start_end )
@ -153,9 +165,10 @@ def review(match_id, race_number, base_dir, db_url, start_range=(0, 5), finish_r
time_offset = float ( black_end . split ( ' : ' ) [ 1 ] )
time_offset = float ( black_end . split ( ' : ' ) [ 1 ] )
else :
else :
found = len ( lines )
found = len ( lines )
logger . warning ( " Unable to detect start (expected 1 black interval, but found {} ) " . format ( found ) )
logger . warning ( " Unable to detect start (expected 1 black interval, but found {} ), re-cutting with timestamps " . format ( found ) )
raise CantFindStart ( racer , found )
cut_to_file ( logger , start_path , base_dir , racer , start_start , start_end , frame_counter = True )
time_offset = datetime . timedelta ( seconds = time_offset )
raise CantFindStart ( racer , racer_number , found , start_path )
time_offset = datetime . timedelta ( seconds = time_offset - start_range [ 0 ] )
# start each racer's finish video at TIME_OFFSET later, so they are the same
# start each racer's finish video at TIME_OFFSET later, so they are the same
# time since their actual start.
# time since their actual start.