diff --git a/common/common/segments.py b/common/common/segments.py index 341b5f1..a7ad4f9 100644 --- a/common/common/segments.py +++ b/common/common/segments.py @@ -231,7 +231,7 @@ def best_segments_by_start(hour): Note this means this function may perform os.stat()s. """ try: - segment_paths = os.listdir(hour) + segment_paths = [path for path in os.listdir(hour) if path.endswith('.ts')] except OSError as e: if e.errno != errno.ENOENT: raise @@ -313,7 +313,8 @@ def ffmpeg_cut_segment(segment, cut_start=None, cut_end=None): args += ['-f', 'mpegts', '-'] # run it logging.info("Running segment cut with args: {}".format(" ".join(args))) - return subprocess.Popen(args, stdout=subprocess.PIPE) + p = subprocess.Popen(args, stdout=subprocess.PIPE, stderr=subprocess.PIPE, stdin=subprocess.PIPE) + return p def ffmpeg_cut_stdin(output_file, cut_start, duration, encode_args): diff --git a/cut_races.py b/cut_races.py index 1cce0ad..2664521 100644 --- a/cut_races.py +++ b/cut_races.py @@ -17,18 +17,23 @@ race_runs contains time for each racer """ +import datetime +import logging +import os +import sys from getpass import getpass import argh import mysql.connector +from common.segments import get_best_segments, cut_segments INFO_QUERY = """ SELECT match_info.racer_1_name as racer_1, match_info.racer_2_name as racer_2, match_info.cawmentator_name as cawmentator, - match_info.match_id as match_id + match_info.match_id as match_id, match_races.race_number as race_number, races.timestamp as start, race_runs.time as duration @@ -40,10 +45,32 @@ INFO_QUERY = """ """ -def cut_to_file() +def ts(dt): + return dt.strftime("%FT%T") -def main(host='condor.host', user='necrobot-read', password=None, database='season_8'): +class NoSegments(Exception): + pass + + +def cut_to_file(filename, base_dir, stream, start, end, variant='source'): + logging.info("Cutting {}".format(filename)) + segments = get_best_segments( + os.path.join(base_dir, stream, variant).lower(), + start, end, + ) + if None in segments: + logging.warning("Cutting {} ({} to {}) but it contains holes".format(filename, ts(start), ts(end))) + if not segments or set(segments) == {None}: + raise NoSegments("Can't cut {} ({} to {}): No segments".format(filename, ts(start), ts(end))) + with open(filename, 'w') as f: + for chunk in cut_segments(segments, start, end): + f.write(chunk) + + +def main(host='condor.host', user='necrobot-read', password=None, database='season_8', base_dir='.', output_dir='.'): + logging.basicConfig(level=logging.INFO) + if password is None: password = getpass("Password? ") conn = mysql.connector.connect( @@ -54,11 +81,32 @@ def main(host='condor.host', user='necrobot-read', password=None, database='seas cur.execute(INFO_QUERY) data = cur.fetchall() + data = [ + [item.encode('utf-8') if isinstance(item, unicode) else item for item in row] + for row in data + ] + + logging.info("Got info on {} races".format(len(data))) for racer1, racer2, cawmentator, match_id, race_number, start, duration in data: end = start + datetime.timedelta(seconds=duration/100.) - name = "-".join([racer1, racer2, match_id, race_number]) - + base_name = "-".join(map(str, [racer1, racer2, match_id, race_number])) + + items = [(racer1, racer1), (racer2, racer2)] + if cawmentator: + items.append(("cawmentary", cawmentator)) + for name, stream in items: + try: + cut_to_file( + os.path.join(output_dir, "{}-{}.ts".format(base_name, name)), + base_dir, stream, start, end, + ) + except NoSegments as e: + logging.warning(e) + except Exception as e: + logging.exception("Failed to cut {}-{}.ts ({} to {})".format( + base_name, name, ts(start), ts(end), + ), exc_info=True) if __name__ == '__main__':