Skip to content

Instantly share code, notes, and snippets.

@Frechdachs
Last active February 13, 2021 06:33
Show Gist options
  • Save Frechdachs/f3786efb6ae28c007e383acdadfac6d4 to your computer and use it in GitHub Desktop.
Save Frechdachs/f3786efb6ae28c007e383acdadfac6d4 to your computer and use it in GitHub Desktop.
#!/usr/bin/env python3
# Gebbi's makewraw.py
# Modified to work with VapourSynth scripts
from sys import argv
from subprocess import call
from optparse import OptionParser
import string
from os import path, remove, rename
import binascii
# modify stuff (paths, settings) from here
vspipe = 'vspipe'
x264 = 'x264-10bit'
mkvmerge = 'mkvmerge'
x264settings = '--crf 22 --preset fast --tune fastdecode'
ffmpeg = 'ffmpeg'
scxvid = 'scxvid'
# until here
def convertpassfile(name):
with open('{}.temp.pass'.format(name), 'r') as passfile, \
open('{}.qp.txt'.format(name), 'w') as qpfile:
counter = 0
for line in passfile:
counter += 1
if line[0] == 'i':
qpfile.write('{} I -1\n'.format(str(counter-4)))
def runjob(vpy, audio, keepall, keepqp, crc):
name = path.splitext(vpy)[0]
# run XviD pass
print('\n\n############ RUNNING 1st PASS (XviD) ############\n\n')
call('"{vspipe}" --y4m "{name}.vpy" - | "{ffmpeg}" -i - -f yuv4mpegpipe -vf scale=640:360 -pix_fmt yuv420p -vsync drop - | "{scxvid}" "{name}.temp.pass"'
.format(vspipe=vspipe, name=name, ffmpeg=ffmpeg, scxvid=scxvid), shell=True)
# convert XviD pass file to x264 qp file
convertpassfile(name)
# run x264 pass
print('\n\n############ RUNNING 2nd PASS (x264) ############\n\n')
qpfile = '{}.qp.txt'.format(name)
output = '{}_noaudio.mkv'.format(name)
cmd = '"{vspipe}" --y4m "{vpy}" - | "{x264}"'.format(vspipe=vspipe, vpy=vpy, x264=x264)
cmd = ' '.join([cmd, x264settings])
cmd = ' '.join([cmd, '--demuxer y4m --qpfile "{qpfile}" --output "{output}" -'.format(qpfile=qpfile, output=output)])
call(cmd, shell=True)
# mux audio, if needed
if audio:
print('\n\n############ MUXING AUDIO ############\n\n')
oldmkv = output
output = '{}.mkv'.format(name)
call([mkvmerge, '-o', output, oldmkv, audio])
if path.isfile(output):
remove(oldmkv)
if crc:
with open(output, 'rb') as wraw:
crc32sum = binascii.crc32(wraw.read()) & 0xffffffff
crc32sum = '{:08X}'.format(crc32sum)
outputsplit = path.splitext(output)
rename(output, '{}[{}]{}'.format(outputsplit[0], crc32sum, outputsplit[1]))
# do a clean-up, if needed
if not keepall:
remove('{}.temp.pass'.format(name))
if not keepqp and not keepall:
remove(qpfile)
def main(args):
opt = OptionParser(description='Does a 2-pass encode, 1st pass XviD, 2nd pass x264, converting XviD keyframe data to x264 keyframe data.',
version='makewraw v0.3', usage='makewraw.py [options] [(optional) vpy-file]')
opt.add_option('--audio', '-a', action='store', help='Specify audiofile to mux after encode', dest='audio')
opt.add_option('--jobs', '-j', action='store', help='Specify jobs file to rotate through', dest='jobs')
opt.add_option('--keepqp', action='store_true', help='Do not remove QP-File after x264 pass', dest='keepqp')
opt.add_option('--keepall', action='store_true', help='Do not remove temp files after x264 pass', dest='keepall')
opt.add_option('--crc', '-c', action='store_true', help='Calculate CRC32 hash and append it to the filename of the output', dest='crc')
(option, arg) = opt.parse_args(args)
if len(arg) == 0 and not option.jobs:
opt.error("No VapourSynth script or jobs file specified. \nUse --help for more information.")
if not option.jobs:
runjob(arg[0], option.audio, option.keepall, option.keepqp, option.crc)
else:
# rotate through jobs
with open(option.jobs, 'r+') as jobfile:
jobcont = jobfile.readlines()
while len(jobcont) > 0:
if jobcont[0].strip():
currvpy, curraud = [x.strip() for x in jobcont[0].split('.vpy')]
currvpy = '{}.vpy'.format(currvpy)
if curraud == '-':
curraud = None
print('\nVideo: {}\nAudio: {}'.format(currvpy, str(curraud)))
runjob(currvpy, curraud, option.keepall, option.keepqp, option.crc)
del jobcont[0]
jobfile.seek(0)
jobfile.writelines(jobcont)
jobfile.truncate()
jobfile.seek(0)
jobcont = jobfile.readlines()
print('\nDone.')
if __name__ == '__main__':
main(argv[1:])
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment