Skip to content

Commit b792168

Browse files
committed
CLI rewrite using argparse, fix title, add -peek option
learn more about the CLI on the wiki
1 parent 5ba6310 commit b792168

1 file changed

Lines changed: 108 additions & 55 deletions

File tree

smoothie.py

Lines changed: 108 additions & 55 deletions
Original file line numberDiff line numberDiff line change
@@ -1,91 +1,144 @@
1-
from sys import argv,exit # parse args
2-
from os import path # split file extension
1+
from argparse import ArgumentParser
2+
from sys import argv,exit
3+
from os import path, system
34
from configparser import ConfigParser
4-
from subprocess import run # Run vs
5-
from random import choice # Randomize the smoothie's flavor))
5+
from subprocess import run
6+
from random import choice # Randomize smoothie's flavor
67

78
# Bool aliases
89
yes = ['True','true','yes','y','1']
910
no = ['False','false','no','n','0','null','',None]
1011

11-
if len(argv) == 1:
12-
print('''
13-
using Smoothie from the command line:
12+
parser = ArgumentParser()
13+
parser.add_argument("-peek", "-p", help="render a specific frame (outputs an image)", action="store", nargs=1, metavar='752', type=int)
14+
parser.add_argument("-trim", "-t", help="Trim out the frames you don't want to use", action="store", nargs=1, metavar='0:23,1:34', type=str)
15+
parser.add_argument("-dir", help="opens the directory where Smoothie resides", action="store_true" )
16+
parser.add_argument("-recipe", "-rc", help="opens default recipe.ini", action="store_true" )
17+
parser.add_argument("--config", "-c", help="specify override config file", action="store", nargs=1, metavar='PATH', type=str)
18+
parser.add_argument("--encoding","-enc", help="specify override ffmpeg encoding arguments", action="store", type=str)
19+
parser.add_argument("-verbose", "-v", help="increase output verbosity", action="store_true" )
20+
parser.add_argument("-curdir", "-cd", help="save all output to current directory", action="store_true", )
21+
parser.add_argument("-input", "-i", help="specify input video path(s)", action="store", nargs="+", metavar='PATH', type=str)
22+
parser.add_argument("-vpy", help="specify a VapourSynth script", action="store", nargs=1, metavar='PATH', type=str)
23+
args = parser.parse_args()
24+
25+
if args.dir:
26+
run(f'explorer {path.dirname(argv[0])}')
27+
exit(0)
28+
if args.recipe:
29+
recipe = path.abspath(path.join(path.dirname(__file__), "settings/recipe.ini"))
30+
if path.exists(recipe) == False:
31+
print("config path does not exist (are you messing with files?), exitting")
32+
run('powershell -NoLogo')
33+
run(f'explorer {recipe}')
34+
exit(0)
1435

15-
sm "D:\Video\input1.mp4" "D:\Video\input2.mp4" ...
16-
Simply give in the path of the videos you wish to queue to smoothie
1736

18-
sm config.extension "D:\Video\input1.mp4" "D:\Video\input2.mp4" ...
19-
You can also make the first argument be your custom config file's name, it'll look for it in the settings folder
20-
''')
21-
exit(0)
37+
conf = ConfigParser()
2238

23-
def ensure(file, desc):
24-
if path.exists(file) == False:
25-
print(f"{desc} file not found: {file}")
26-
exit(1)
39+
if args.config:
40+
config_filepath = path.abspath(args.config[0])
41+
conf.read(config_filepath)
42+
else:
43+
config_filepath = path.abspath(path.join(path.dirname(__file__), "settings/recipe.ini"))
44+
conf.read(config_filepath)
2745

28-
if argv == [argv[0],'folder']:
29-
run(f'explorer {path.dirname(argv[0])}')
30-
exit(0)
46+
if path.exists(config_filepath) in [False,None]:
47+
print("config path does not exist, exitting")
48+
run('powershell -NoLogo')
49+
elif args.verbose:
50+
print(f"VERBOSE: using config file: {config_filepath}")
3151

32-
if path.splitext(argv[1])[1] in ['.ini','.txt']:
52+
if args.input in [no, None]:
53+
parser.parse_args('-h'.split()) # If the user does not pass any args, just redirect to -h (Help)
3354

34-
if path.dirname(argv[1]) == '': # If no directory, look for it in the settings folder
35-
recipe = path.join(path.dirname(argv[0]), f"settings\\{argv[1]}")
36-
config_filepath = recipe
37-
conf = ConfigParser()
38-
conf.read(recipe)
39-
else: # If there is a directory, it's a full path so just load it in
40-
conf = ConfigParser()
41-
conf.read(argv[1])
42-
config_filepath = argv[1]
55+
round = 0 # Reset the round counter
4356

44-
queue = argv[2:]
45-
else:
46-
recipe = path.join(path.dirname(__file__), "settings\\recipe.ini")
47-
config_filepath = recipe
48-
conf = ConfigParser()
49-
conf.read(recipe)
50-
queue = argv[1:]
57+
for video in args.input: # Loops through every single video
58+
59+
# Title
60+
61+
round += 1
62+
63+
title = "Smoothie - " + path.basename(video)
64+
65+
if len(args.input) > 1:
66+
title = f'[{round}/{len(args.input)}] ' + title
5167

52-
for video in queue:
68+
system(f"title {title}")
69+
70+
# Suffix
5371

5472
if str(conf['misc']['flavors']) in [yes,'fruits']:
5573
flavors = [
56-
'Strawberry','Blueberry','Raspberry','Blackberry','Cherry','Cranberry','Coconut','Pineapple','Kiwi'
57-
'Peach','Apricot','Dragonfuit','Grapefruit','Melon','Papaya','Watermelon','Banana','Apple','Pear','Orange'
74+
'Berry','Cherry','Cranberry','Coconut','Kiwi','Avocado','Durian','Lemon','Lime','Fig','Mirabelle',
75+
'Peach','Apricot','Grape','Melon','Papaya','Banana','Apple','Pear','Orange','Mango','Plum','Pitaya'
5876
]
5977
else:
6078
flavors = ['Smoothie']
6179

62-
filename, ext = path.splitext(video)
80+
# Extension
81+
82+
if args.peek:
83+
ext = '.png'
84+
elif conf['misc']['container'] in no:
85+
ext = path.splitext(video)[1]
86+
else:
87+
ext = conf['misc']['container']
88+
89+
filename = path.basename(path.splitext(video)[0])
6390

64-
if conf['misc']['folder'] in no:
91+
# Directory
6592

93+
if args.curdir:
94+
outdir = path.abspath(path.curdir)
95+
elif conf['misc']['folder'] in no:
6696
outdir = path.dirname(video)
6797
else:
6898
outdir = conf['misc']['folder']
6999

70-
out = path.join(outdir, filename + f' - {choice(flavors)}' + ext)
100+
out = path.join(outdir, filename + f' - {choice(flavors)}{ext}')
71101

72102
count=2
73103
while path.exists(out):
74-
out = path.join(outdir, filename + f' - {choice(flavors)}' + f' ({count})' + ext)
104+
out = path.join(outdir, f'{filename} - {choice(flavors)} ({count}){ext}')
75105
count+=1
76106

107+
# VapourSynth
108+
77109
vspipe = path.join(path.dirname((path.dirname(__file__))),'VapourSynth','VSPipe.exe')
78-
vpy = 'blender.vpy'
110+
111+
if args.vpy:
112+
113+
if path.dirname(args.vpy[0]) in no:
114+
115+
vpy = path.join( path.dirname(__file__), (args.vpy[0]) )
116+
else:
117+
vpy = path.abspath(args.vpy[0])
118+
else:
119+
vpy = path.abspath(path.join(path.dirname(__file__),'blender.vpy'))
79120

80-
command = [ # Split in two for readability
81-
82-
f"cmd /c {vspipe} -y \"{path.join(path.dirname(__file__), vpy)}\" --arg input_video=\"{video}\" --arg config_filepath=\"{config_filepath}\"",
83-
f"- | {conf['encoding']['process']} -hide_banner -loglevel warning -stats -i - {conf['encoding']['args']} \"{out}\""
84-
# -i \"{video}\" -map 0:v -map 1:a?
121+
command = [ # This is the master command, it gets appended some extra output args later down
122+
f'{vspipe} -y "{vpy}" --arg input_video="{video}" --arg config_filepath="{config_filepath}" ',
123+
f'- | {conf["encoding"]["process"]} -hide_banner -loglevel warning -stats -i - ',
85124
]
86-
if (conf['misc']['verbose']) in yes:
87-
print(command)
88-
print(f"VSPipe: {vspipe}")
89-
print(f"VIDEO: {video}")
90125

91-
run(' '.join(command),shell=True)
126+
if args.peek:
127+
frame = int(args.peek[0]) # Extracting the frame passed from the singular array
128+
command[0] += f'--start {frame} --end {frame}'
129+
command[1] += f' "{out}"' # No need to specify audio map, simple image output
130+
elif args.trim:
131+
command[0] += f'--arg trim="{args.trim}"'
132+
command[1] += f'{conf["encoding"]["args"]} "{out}"'
133+
else:
134+
# Adds as input the video to get it's audio tracks and gets encoding arguments from the config file
135+
command[1] += f'-i "{path.abspath(video)}" -map 0:v -map 1:a? {conf["encoding"]["args"]} "{out}"'
136+
137+
if args.verbose:
138+
command[0] += ' --arg verbose=True'
139+
for cmd in command: print(cmd)
140+
print(f"Queuing video: {video}")
141+
142+
run(' '.join(command),shell=True)
143+
144+
system(f"title [{round}/{len(args.input)}] Smoothie - Finished! (EOF)")

0 commit comments

Comments
 (0)