#!/usr/bin/env python
#-*- coding: iso-8859-1 -*-
# mkdvd.py, 0.3
#
# by abgdf, 2009/2010, Licence GNU GPL, Version 3:
# http://www.gnu.org/licenses/gpl.html
import os
import sys
class DVDMaker:
def __init__(self):
self.options = {"clean" : True,
"quiet" : True,
"subdirname" : "mydvd",
"encoder" : "mencoder",
"runencoder" : True,
"authorize" : True,
"srate" : False,
"titleend" : False,
"16:9" : False }
self.menc = "mencoder -oac lavc -ovc lavc -of mpeg -mpegopts format=dvd -vf scale=352:576,harddup -lavcopts vcodec=mpeg2video:vrc_buf_size=1835:vrc_maxrate=9800:vbitrate=5000:keyint=15:acodec=ac3:abitrate=192:aspect=4/3 -ofps 25 -o outfile.avi infile.avi"
self.ffm = "ffmpeg -i infile.avi -target pal-dvd -aspect 4:3 outfile.avi"
self.step = 1
self.args = sys.argv[1:]
self.processArgs()
# Setting options "srate" often leads to segfaults on my system :(.
if self.options["srate"]:
self.menc = "mencoder -oac lavc -ovc lavc -of mpeg -mpegopts format=dvd -vf scale=352:576,harddup -srate 48000 -af lavcresample=48000 -lavcopts vcodec=mpeg2video:vrc_buf_size=1835:vrc_maxrate=9800:vbitrate=5000:keyint=15:acodec=ac3:abitrate=192:aspect=4/3 -ofps 25 -o outfile.avi infile.avi"
self.subdir = ""
self.filesdir = ""
self.foutnames = []
self.xml = []
self.xmlfname = ""
self.makeDvd()
def processArgs(self):
if len(self.args) < 1:
print "Usage: mkdvd.py title1.avi [title2.avi title3.avi ...] [-v] [--noclean] [-ja] [-je] [-sr] [--encoder=ffmpeg] [--commands]"
sys.exit(1)
if "-h" in self.args or "--help" in self.args:
print
print "mkdvd.py 0.3 by abgdf, 2009/2010 (GNU GPL, V.3):"
print "Create DVD-type movie-files (VOB etc.) from one or more input-files using mencoder or ffmpeg and dvdauthor."
print
print "Usage: mkdvd.py title1.avi [title2.avi title3.avi ...]"
print
print "Options:"
print
print "-h, --help Print (this) help."
print "-v Verbose: Don't suppress output of mencoder, ffmpeg and dvdauthor."
print "-ja Just authorize: Don't run any encoder."
print " Files must already exist as './mydvd/files/dvd01.mpg' and so on."
print " No cleaning up by default."
print "-je Just encode. Exit without authorizing."
print '-sr Use original mencoder-line including "-srate 48000".'
print "-te After a title has been played, playing ends"
print " (default: playing continues with the next title)."
print "-16 Use 16:9 picture-format instead of 4:3 (default)."
print "--encoder=ffmpeg Use ffmpeg as encoder (default is mencoder)."
print "--noclean Leave temporary (usually large) files in './mydvd/files'."
print "--commands Show encoder-commands and exit."
print
sys.exit(0)
if "--commands" in self.args:
print
print "Encoder-Commands:"
print
if "-sr" in self.args:
print "mencoder -oac lavc -ovc lavc -of mpeg -mpegopts format=dvd -vf scale=352:576,harddup -srate 48000 -af lavcresample=48000 -lavcopts vcodec=mpeg2video:vrc_buf_size=1835:vrc_maxrate=9800:vbitrate=5000:keyint=15:acodec=ac3:abitrate=192:aspect=4/3 -ofps 25 -o outfile.avi infile.avi"
else:
print self.menc
print
print self.ffm
print
sys.exit(0)
optchange = (("-v", "quiet", False),
("--noclean", "clean", False),
("--encoder=ffmpeg", "encoder", "ffmpeg"),
("-ja", "runencoder", False),
("-je", "authorize", False),
("-sr", "srate", True),
("-te", "titleend", True),
("-16", "16:9", True))
for i in optchange:
if i[0] in self.args:
self.options[i[1]] = i[2]
while i[0] in self.args:
self.args.remove(i[0])
def makeDvd(self):
self.subdir = os.path.join(os.getcwd(), self.options["subdirname"])
self.filesdir = os.path.join(self.subdir, "files")
self.makeDirs()
if self.options["runencoder"]:
self.runEncoder()
if self.options["authorize"]:
self.getFilenamesToAuthorize()
self.composeXML()
self.runDvdauthor()
if self.options["clean"]:
self.cleanUp()
print
print "Finished:"
if self.options["authorize"]:
print "Directories 'VIDEO_TS' and 'AUDIO_TS' should be in '" + self.subdir + "'."
else:
print "Encoded file(s) should be in '" + self.filesdir + "'."
print "Bye."
print
def makeDirs(self):
if self.options["runencoder"]:
if os.path.exists(self.subdir):
print "Subdirectory '" + self.subdir + "' already exists. Nothing done."
sys.exit(2)
for i in self.args:
if not os.path.isfile(os.path.join(os.getcwd(), i)):
print "Error: File '" + os.path.join(os.getcwd(), i) + "' not found. Aborting."
sys.exit(3)
os.mkdir(self.subdir)
os.mkdir(self.filesdir)
def runEncoder(self):
print
for i in range(len(self.args)):
ffm = ["ffmpeg"]
menc = self.menc.split(" ")
if self.options["16:9"]:
for u in range(len(menc)):
menc[u] = menc[u].replace("aspect=4/3", "aspect=16/9")
for u in range(2):
menc.pop()
if i < 9:
istr = "0" + str(i + 1)
else:
istr = str(i + 1)
self.foutnames.append("dvd" + istr + ".mpg")
ffm.append("-i")
ffm.append(self.args[i])
ffm.extend(["-target", "pal-dvd", "-aspect"])
if self.options["16:9"]:
ffm.append("16:9")
else:
ffm.append("4:3")
ffm.append(os.path.join(self.filesdir, self.foutnames[i]))
menc.append(os.path.join(self.filesdir, self.foutnames[i]))
menc.append(self.args[i])
if self.options["quiet"]:
menc.append("&>/dev/null")
ffm.append("&>/dev/null")
print str(self.step) + ". Running " + self.options["encoder"] + " on '" + self.args[i] + "'."
self.step += 1
if self.options["encoder"] == "mencoder":
comm = " ".join(menc)
else:
comm = " ".join(ffm)
if not self.options["quiet"]:
print
print comm
print
os.system(comm)
for i in range(len(self.foutnames)):
if not os.path.isfile(os.path.join(self.filesdir, self.foutnames[i])):
print
print "Error: File '" + os.path.join(self.filesdir, self.foutnames[i]) + "' missing."
print "Probably " + self.options["encoder"] + " had problems processing file '" + self.args[i] + "'."
print "Aborting."
print
sys.exit(4)
def composeXML(self):
# Composing xml-file for dvdauthor:
self.xml = ['<dvdauthor dest="' + self.subdir + '" >',
' <vmgm/>', ' <titleset>',
' <titles>']
if self.options["16:9"]:
self.xml.append(' <video format="pal" aspect="16:9" />')
else:
self.xml.append(' <video format="pal" aspect="4:3" />')
self.xml.append(' <audio lang="DE" />')
for i in range(len(self.foutnames)):
self.xml.append(' <pgc>')
foutpath = os.path.join(self.filesdir, self.foutnames[i])
self.xml.append(' <vob file="' + foutpath + '" chapters="00:00:00.00" />')
if self.options["titleend"]:
# After playing a title, stop playing:
self.xml.append(' <post>exit;</post>')
else:
# After playing a title, move to the next one, if possible:
if i < len(self.foutnames) - 1:
self.xml.append(' <post>jump title ' + str(i + 2) + ';</post>')
else:
self.xml.append(' <post>exit;</post>')
self.xml.append(' </pgc>')
self.xml.extend((' </titles>',
' </titleset>',
'</dvdauthor>'))
self.xmlfname = os.path.join(self.filesdir, "dvdauthor.xml")
print str(self.step) + ". Writing xml-file."
self.step += 1
fh = file(self.xmlfname, "w")
for i in self.xml:
fh.write(i + "\n")
fh.close()
def runDvdauthor(self):
print str(self.step) + ". Running dvdauthor."
self.step += 1
dvda = "dvdauthor -x " + self.xmlfname
if self.options["quiet"]:
dvda += " &>/dev/null"
os.system(dvda)
def getFilenamesToAuthorize(self):
if not os.path.isdir(self.filesdir):
print "Directory '" + self.filesdir + "' doesn't exists. Nothing done."
sys.exit(5)
self.foutnames = []
a = os.listdir(self.filesdir)
for i in a:
if i.startswith("dvd") and i.endswith(".mpg"):
self.foutnames.append(i)
if not self.foutnames:
print "No files to authorize in '" + self.filesdir + "'. Nothing done."
sys.exit(6)
def cleanUp(self):
if self.options["runencoder"] and self.options["authorize"]:
print str(self.step) + ". Cleaning up."
self.step += 1
for i in self.foutnames:
os.remove(os.path.join(self.filesdir, i))
os.remove(self.xmlfname)
os.rmdir(self.filesdir)
if __name__ == "__main__":
DVDMaker()