Skip to content

Commit

Permalink
yaml to ini, random fruits as output filename suffix, and many fixes
Browse files Browse the repository at this point in the history
configs will now be ini instead of yaml
renaming resampling to frame blending
additional bool aliases
random fruits as output (opt out)
custom output folder
verbose switch
  • Loading branch information
couleurm committed Feb 4, 2022
1 parent 73ca410 commit de61f81
Show file tree
Hide file tree
Showing 4 changed files with 94 additions and 92 deletions.
61 changes: 30 additions & 31 deletions blender.vpy
Original file line number Diff line number Diff line change
@@ -1,68 +1,67 @@
from vapoursynth import core
import vapoursynth as vs
from os import path # To split file extension
from yaml import load, FullLoader
from configparser import ConfigParser
import havsfunc # aka Interframe2

input_video="D:\\Video Vault\\R 01-30 15-30.mkv"
config_filepath="D:\\GitHub\\Smoothie\\settings\\recipe.yaml"

conf = load(open(f"{config_filepath}"), Loader=FullLoader)
conf = ConfigParser()
conf.read(config_filepath)

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

if path.splitext(input_video)[1] == '.avi':
video = core.avisource.AVISource(f"{input_video}")
video = core.fmtc.matrix(clip=video, mat="601", col_fam=vs.YUV, bits=16)
video = core.fmtc.resampling(clip=video, css="420")
video = core.fmtc.bitdepth(clip=video, bits=8)
else:
video = core.ffms2.Source(source=f"{input_video}", cache=False)

if float(conf['misc']['timescale']['in']) != 1: # Input timescale, done before interpolation
video = core.std.AssumeFPS(video, fpsnum=(video.fps * (1 / conf['misc']['timescale']['in'])))
video = core.ffms2.Source(source=input_video, cache=False)

if str(conf['interpolation']['pre interpolation']['enabled']).lower() in yes: # Pre-interpolating with RIFE
if float(conf['timescale']['in']) != 1: # Input timescale, done before interpolation
video = core.std.AssumeFPS(video, fpsnum=(video.fps * (1 / float(conf['timescale']['in']))))

video = core.resize.Bicubic(video, format=vs.RGBS)
if str(conf['interpolation']['pre interpolation']['rife type']).lower() == 'cuda':
from vsrife import RIFE
while video.fps > conf['interpolation']['pre interpolation']['minimum fps']:
video = RIFE(video)
elif str(conf['interpolation']['pre interpolation']['rife type']).lower() == 'ncnn':
video = core.resize.Bicubic(video, format=vs.RGBS)
while video.fps < conf['interpolation']['pre interpolation']['minimum fps']:
video = core.rife.RIFE(video)
video = core.resize.Bicubic(video, format=vs.YUV420P8, matrix_s="709")
# if str(conf['interpolation']['pre interpolation']['enabled']).lower() in yes: # Pre-interpolating with RIFE
#
# video = core.resize.Bicubic(video, format=vs.RGBS)
# if str(conf['interpolation']['pre interpolation']['rife type']).lower() == 'cuda':
# from vsrife import RIFE
# while video.fps > conf['interpolation']['pre interpolation']['minimum fps']:
# video = RIFE(video)
# elif str(conf['interpolation']['pre interpolation']['rife type']).lower() == 'ncnn':
# video = core.resize.Bicubic(video, format=vs.RGBS)
# while video.fps < conf['interpolation']['pre interpolation']['minimum fps']:
# video = core.rife.RIFE(video)
# video = core.resize.Bicubic(video, format=vs.YUV420P8, matrix_s="709")

if str(conf['interpolation']['enabled']).lower() in yes: # Interpolation using Interframe2 (uses SVP-Flow, which is what blur uses)

video = havsfunc.InterFrame(
video,
GPU=True,
NewNum=conf['interpolation']['fps'],
Preset=conf['interpolation']['speed'],
Tuning=conf['interpolation']['tuning'],
OverrideAlgo=conf['interpolation']['algorithm']
NewNum=int(conf['interpolation']['fps']),
Preset=str(conf['interpolation']['speed']),
Tuning=str(conf['interpolation']['tuning']),
OverrideAlgo=int(conf['interpolation']['algorithm'])
)

if float(conf['misc']['timescale']['out']) != 1: # Output timescale, done after interpolation
video = core.std.AssumeFPS(video, fpsnum=(video.fps * conf['misc']['timescale']['out']))
if float(conf['timescale']['out']) != 1: # Output timescale, done after interpolation
video = core.std.AssumeFPS(video, fpsnum=(video.fps * float(conf['timescale']['out'])))

if str(conf['misc']['deduplication']).lower() in yes:
import filldrops
video = filldrops.FillDrops(video, thresh=0.001)

if str(conf['resampling']['enabled']).lower() in yes:
if str(conf['frame blending']['enabled']).lower() in yes:
import weighting
frame_gap = int(video.fps / conf['resampling']['fps'])
blended_frames = int(frame_gap * conf['resampling']['intensity'])
frame_gap = int(video.fps / int(conf['frame blending']['fps']))
blended_frames = int(frame_gap * float(conf['frame blending']['intensity']))
if blended_frames > 0:
if blended_frames % 2 == 0:
blended_frames += 1
weights = weighting.equal(blended_frames)
video = core.frameblender.FrameBlend(video, weights, True)
video = havsfunc.ChangeFPS(video, conf['resampling']['fps'])
video = havsfunc.ChangeFPS(video, int(conf['frame blending']['fps']))

video.set_output()
35 changes: 35 additions & 0 deletions settings/recipe.ini
Original file line number Diff line number Diff line change
@@ -0,0 +1,35 @@
# Will uses SVP-Flow to "guess" frames for a smoother resampling, slowers the higher you go
[interpolation]
enabled=y
# This completly disables interpolation, same thing goes for resampling
fps=960
speed=medium
tuning=weak
algorithm=23

# Blends the frames to make a smoother video with a lower FPS (e.g 60FPS)
[frame blending]
enabled=y
fps=60
intensity=1.27
# The higher the frameblending's fps, the higher you can set this to

[encoding] # How your video will be encoded
process=ffmpeg
args=-c:v hevc_nvenc -preset p7 -rc constqp -qp 18

[misc]
folder=
# Set a folder here if you wish to redirect all outputted videos to a specific folder, else leave it empty
deduplication=y
# Finds duplicate frames (e.g if you had encoding lag) and tries patching them with interpolation
container=mp4
# If you prefer mkv, or would like to use uncompressed avi
verbose=false
flavors=fruits
# If you wish to disable random fruits being added to your video's prefixes, make this empty

[timescale]
in=1
out=1
# If your clips are slowed down / you wish to accelerate your clips before resampling
27 changes: 0 additions & 27 deletions settings/recipe.yaml

This file was deleted.

63 changes: 29 additions & 34 deletions smoothie.py
Original file line number Diff line number Diff line change
@@ -1,9 +1,13 @@
from sys import argv # parse args
from os import _exit, path # split file extension
from yaml import load,FullLoader # parse the config
from os import path # split file extension
from configparser import ConfigParser
from subprocess import run # Run vs
from random import choice # Randomize the smoothie's flavor))

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

if len(argv) == 1:
print('''
using Smoothie from the command line:
Expand All @@ -21,68 +25,59 @@ def ensure(file, desc):
print(f"{desc} file not found: {file}")
exit(1)

if path.splitext(argv[1])[1] in ['.conf','.cfg','.txt','.json','.yml','yaml']:
if path.splitext(argv[1])[1] in ['.ini','.txt']:

if path.dirname(argv[1]) == '': # If no directory, look for it in the settings folder
recipe = path.join(path.dirname(argv[0]), f"settings\\{argv[1]}")
config_filepath = recipe
conf = load(open(recipe), Loader=FullLoader)
conf = ConfigParser()
conf.read(recipe)
else: # If there is a directory, it's a full path so just load it in
conf = load(open(argv[1]), Loader=FullLoader)
conf = ConfigParser()
conf.read(argv[1])
config_filepath = argv[1]

queue = argv[2:]
else:
recipe = path.join(path.dirname(argv[0]), "settings\\recipe.yaml")
recipe = path.join(path.dirname(argv[0]), "settings\\recipe.ini")
config_filepath = recipe
conf = load(open(recipe), Loader=FullLoader)
conf = ConfigParser()
conf.read(recipe)
queue = argv[1:]

for video in queue:

if ['conf']['misc']['random flavors'] == True:
if str(conf['misc']['flavors']) in [yes,'fruits']:
flavors = [
'Strawberry'
'Blueberry'
'Raspberry'
'Blackberry'
'Cherry'
'Cranberry'
'Coconut'
'Peach'
'Apricot'
'Dragonftui'
'Grapefruit'
'Melon'
'Papaya'
'Watermelon'
'Banana'
'Pineapple'
'Apple'
'Kiwi'
'Strawberry','Blueberry','Raspberry','Blackberry','Cherry','Cranberry','Coconut','Pineapple','Kiwi'
'Peach','Apricot','Dragonfuit','Grapefruit','Melon','Papaya','Watermelon','Banana','Apple','Pear','Orange'
]
else:
flavors = ['Smoothie']

filename, ext = path.splitext(video)

if conf['misc']['custom output folder'] in [None,'null','','none','no','n']:
if conf['misc']['folder'] in no:

outdir = path.dirname(video)
else:
outdir = conf['misc']['custom output folder']
outdir = conf['misc']['folder']

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

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

command = [ # Split in two for readability
f"vspipe -i \"{path.join(path.dirname(argv[0]), 'blender.vpy')}\" --arg input_video=\"{video}\" --arg config_filepath=\"{config_filepath}\" --container y4m",
f"-| {conf['encoding']['process']} -hide_banner -loglevel warning -stats -i - {conf['encoding']['args']} \"{out}\""

f"cmd /c vspipe -y \"{path.join(path.dirname(argv[0]), 'blender.vpy')}\" --arg input_video=\"{video}\" --arg config_filepath=\"{config_filepath}\"",
f"- | {conf['encoding']['process']} -hide_banner -loglevel warning -stats -i - {conf['encoding']['args']} \"{out}\""
# -i \"{video}\" -map 0:v -map 1:a?
]
print(command)
if (conf['misc']['verbose']) in yes:
print(command)
print(f"VIDEO: {video}")

run(' '.join(command),shell=True)
run(' '.join(command),shell=True)

0 comments on commit de61f81

Please sign in to comment.