Created
July 19, 2018 08:12
-
-
Save flablog/58dddc550bb1d049c985e720ea6ab0ac to your computer and use it in GitHub Desktop.
Play : simple command line to play shots as sequences
This file contains 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
#!/usr/bin/python | |
'''This scripts reads CSVs prepared from a XML edit export, | |
and prepares a Melt command to play shots as a sequence | |
https://mltframework.org/twiki/bin/view/MLT/MltMelt | |
''' | |
import argparse | |
import os | |
import sys | |
import glob | |
from pprint import pprint | |
project = "Dilili" | |
parser = argparse.ArgumentParser() | |
parser.add_argument("episode", type=str, | |
default="DIL", | |
help="episode name") | |
parser.add_argument("seq", type=int, | |
help="sequence number (without S)") | |
parser.add_argument("shots", | |
type=int, | |
action='store', | |
nargs='*', | |
help="shot number(s), without P") | |
parser.add_argument("-r", "--range", | |
type=str, | |
help="range start:end :end (from beginning to the end) start: (from start to the end)") | |
parser.add_argument("-rv", help="play in rv instead of melt", | |
action="store_true") | |
parser.add_argument("-dj", help="play one shot in djv_view", | |
action="store_true") | |
parser.add_argument("-v", '--verbose', help="verbose mode", | |
action="store_true") | |
parser.add_argument('--list-only', help="activate verbose mode and does not execute the commad at the end", | |
action="store_true") | |
parser.add_argument("-compo", help="play compo OUT image sequence instead of movie preview", | |
action="store_true") | |
args = parser.parse_args() | |
if args.list_only: | |
args.verbose = True | |
start = 0 | |
end = 999999 | |
# If a range is specified | |
if args.range and ":" not in args.range: | |
print("range invalid, should be start:end or :end or start:") | |
elif args.range and ":" in args.range: | |
s, e = args.range.split(":") | |
if s and s.isdigit(): | |
start = int(s) | |
if e and e.isdigit(): | |
end = int(e) | |
# If not argument provided | |
if len(sys.argv) < 2: | |
print("Provide a least a sequence number to play > ex: play 2") | |
sys.exit() | |
root = "/u/production/%s/%s/" % (project, episode) | |
seq = "S%02i" % args.seq | |
wip = args.wip | |
compo = args.compo | |
# Checking if episode or sequence exists | |
if not os.path.exists(root): | |
print("Episode %s DOES NOT EXISTS" % root) | |
sys.exit() | |
if not os.path.exists(root + seq): | |
print("SEQUENCE DOES NOT EXISTS IN %s" % root) | |
sys.exit() | |
# Checking if there is a CSV file available for that sequence | |
current = root + seq + "/EDIT/current/" | |
EDL_path = root + seq + "/EDIT/EDL/*.csv" | |
EDLs = glob.glob(EDL_path) | |
if not EDLs: | |
print("NO EDL (CSV) FILE FOUND ON : %s" % EDL_path) | |
sys.exit() | |
# Grabbing the last version : | |
EDLs.sort() | |
last_EDL = EDLs[-1] | |
if args.verbose: | |
print("Using following EDL : %s" % last_EDL) | |
# Parsing the EDL file and listing all the shots | |
shots = [] | |
f = open(last_EDL, 'r') | |
lines = f.readlines() | |
f.close() | |
if args.verbose: | |
if args.range: | |
print("Range set : %i:%i" % (start, end)) | |
else: | |
print("default range : %i:%i" % (start, end)) | |
in_range = False | |
start_consumed = False | |
for l in lines: | |
if not l or l.startswith('#') or ',' not in l: | |
print("skipped : %s" % l) | |
continue | |
shot = l.split(',')[0] | |
if shot.startswith(episode): | |
if args.range: | |
shot_id = int(shot.split("_")[-1].split("P")[1]) | |
if in_range is False: | |
if shot_id == start or (start == 0 and start_consumed is False): | |
in_range = True | |
start_consumed = True | |
shots.append(shot) | |
else: | |
if shot_id == end: | |
in_range = False | |
shots.append(shot) | |
if args.shots: | |
for s in args.shots: | |
if "P%04i" % s in shot and shot not in shots: | |
shots.append(shot) | |
elif args.range: | |
continue | |
else: | |
shots.append(shot) | |
if args.verbose: | |
print(" # List of shots to be screened : ") | |
pprint(shots) | |
print("%i Shots" % len(shots)) | |
# Now the parsing has been done, and the list is ready | |
# Preparing the command line, default is melt, but could be rv ou djv_view | |
cmd = "melt " | |
if args.rv: | |
cmd = "rv -play -l " | |
if args.dj: | |
cmd = "djv_view " | |
# For each shot of the list, fetches the shot | |
# Depending on parameters provided. Default choice is using "CURRENT" | |
# The command ('cmd' variable) will be incremented for each shot | |
for s in shots: | |
if wip is False and compo is False: | |
# CURRENT | |
path = current + "%s.mov" % s | |
if os.path.exists(path): | |
cmd += "%s " % path | |
else: | |
print("Missing shot : %s" % s) | |
elif compo is True: | |
# COMPO IMAGE SEQUENCE | |
episode, seq, shot = s.split("_") | |
compo_path = root + "%s/%s/Compo-Render/OUT" % (seq, shot) | |
if os.path.exists(compo_path): | |
cmd += "%s " % compo_path | |
else: | |
print("Missing shot : %s" % s) | |
elif wip is True: | |
# WORK IN PROGRESS MOVIE, NOT THE CURRENT ONE | |
# This is more depending on our workflow, where a wip preview | |
# might not be in the CURRENT folder yet until publishing the | |
# work file (like the animation file). | |
episode, seq, shot = s.split("_") | |
wip_path = root + "%s/%s/*-Movie/%s_*.mov" % (seq, shot, s) | |
results = glob.glob(wip_path) | |
oldest_path = 0 | |
file_path = None | |
for f in results: | |
st = os.stat(f) | |
if st.st_mtime > oldest_path: | |
oldest_path = st.st_mtime | |
file_path = f | |
if file_path: | |
cmd += "%s " % file_path | |
else: | |
print("Missing shot : %s" % s) | |
if args.verbose: | |
print(cmd) | |
# The command is now ready, and we ask the system to execute it | |
if args.list_only is False: | |
os.system(cmd) |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment