Created
November 17, 2011 10:17
-
-
Save SAPikachu/1372854 to your computer and use it in GitHub Desktop.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
import sys | |
import re | |
import os | |
def read_tc_v1(f, params): | |
frame_count = None | |
if "frame-count" in params: | |
frame_count = int(params["frame-count"]) | |
parts = [] | |
default_fps = None | |
for line in f: | |
line = line.strip() | |
if line.startswith("#"): | |
if frame_count is None: | |
m = re.match(r"^# vfr stats: .* (\d+) - total", line) | |
if m: | |
frame_count = int(m.group(1)) | |
continue | |
if not line: | |
continue | |
if line.lower().startswith("assume "): | |
if default_fps: | |
raise ValueError("Found multiple assume line") | |
default_fps = float(line[7:].strip()) | |
continue | |
if not default_fps: | |
raise ValueError("Missing assume line") | |
current_part = line.split(",") | |
parts.append([ | |
int(current_part[0]), | |
int(current_part[1]), | |
float(current_part[2])]) | |
parts.sort(key=lambda x: x[0]) | |
if len(parts) == 0: | |
raise ValueError("Timecode file is empty") | |
if not frame_count: | |
frame_count = parts[-1][1] + 1 | |
print("Warning: Frame count not specified, and this is not TIVTC-generated timecode file, using guessed frame count ({0})".format(frame_count)) | |
ret = [] | |
for i in range(frame_count): | |
while True: | |
if len(parts) == 0: | |
current_fps = default_fps | |
break | |
elif i < parts[0][0]: | |
current_fps = default_fps | |
break | |
elif i > parts[0][1]: | |
parts.pop(0) | |
continue | |
else: | |
current_fps = default_fps | |
break | |
ret.append(1000.0 / current_fps) | |
return ret | |
def read_tc_v2(f, params): | |
last_timestamp = None | |
ret = [] | |
for line in f: | |
line = line.strip() | |
if not line or line.startswith("#"): | |
continue | |
current_timestamp = float(line) | |
if last_timestamp is not None: | |
ret.append(current_timestamp - last_timestamp) | |
last_timestamp = current_timestamp | |
if last_timestamp: | |
if "default-fps" in params: | |
ret.append(1000.0 / float(params["default-fps"])) | |
else: | |
ret.append(ret[-1]) | |
return ret | |
# !! returns duration for each frame | |
def read_tc(fn, params): | |
try: | |
with open(fn, "r") as f: | |
while True: | |
line = f.readline() | |
if not line: | |
raise ValueError("File is empty") | |
sys.exit(1) | |
line = line.strip() | |
if not line: | |
continue | |
if line.lower() == "# timecode format v1": | |
return read_tc_v1(f, params) | |
elif line.lower() == "# timecode format v2": | |
return read_tc_v2(f, params) | |
else: | |
raise ValueError("Invalid header") | |
except ValueError as e: | |
raise ValueError("Invalid timecode file {0}: {1}".format(fn, e.args)) | |
def do_append(files, output): | |
tc = [] | |
for f in files: | |
tc += read_tc(f["name"], f["params"]) | |
with open(output, "w") as f: | |
f.write("# timecode format v2\n") | |
current_timestamp = 0.0 | |
for x in tc: | |
f.write("{0:6f}".format(current_timestamp)) | |
f.write("\n") | |
current_timestamp += x | |
def parse_options(options): | |
files = [] | |
current_file = None | |
options = list(options) | |
while options: | |
current_option = options.pop(0) | |
if current_option.startswith("--"): | |
current_file["params"][current_option[2:]] = options.pop(0) | |
continue | |
else: | |
if current_file: | |
files.append(current_file) | |
current_file = { | |
"name": current_option, | |
"params": {}, | |
} | |
if len(files) < 2: | |
return None | |
return { | |
"files": files, | |
"output": current_file["name"], | |
} | |
def print_usage(): | |
script_name = os.path.basename(sys.argv[0]) | |
print("Usage:") | |
print("{0} <input 1> <input 2> [<input N> ...] <output>" \ | |
.format(script_name)) | |
print("") | |
print("Example:") | |
print("{0} tcin_1.txt tcin_2.txt tcout.txt".format(script_name)) | |
print("") | |
print("Timecode V1 files are supported, but if it isn't generated by TIVTC, you need to specify frame count like:") | |
print("{0} tcv1.txt --frame-count 34567 tcv2.txt tcout.txt".format(script_name)) | |
pass | |
if __name__ == "__main__": | |
options = parse_options(sys.argv[1:]) | |
if not options: | |
print_usage() | |
sys.exit(1) | |
do_append(**options) |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment