Skip to content

Instantly share code, notes, and snippets.

@dpetzold
Created August 20, 2010 22:00
Show Gist options
  • Star 6 You must be signed in to star a gist
  • Fork 2 You must be signed in to fork a gist
  • Save dpetzold/541290 to your computer and use it in GitHub Desktop.
Save dpetzold/541290 to your computer and use it in GitHub Desktop.
Convert and video to ipod viewable using ffmpeg capturing the output to a display the encoding progress.
#!/usr/bin/python
import fcntl
import optparse
import os
import progressbar
import re
import select
import shlex
import subprocess
import sys
import time
class ElapsedWidget(progressbar.ProgressBarWidget):
def update(self, pbar):
return time.strftime('Elapsed: %H:%M:%S', time.gmtime(pbar.seconds_elapsed))
class EncodingProgressBar(object):
def __init__(self, filename):
self.filename = filename
self.maxval = self.duration
widgets = [
filename[:20], ' ',
progressbar.Percentage(), ' ',
progressbar.Bar(marker=progressbar.RotatingMarker()), ' ',
progressbar.ETA(), ' ', ElapsedWidget(),
]
self.pbar = progressbar.ProgressBar(
widgets=widgets,
maxval=self.maxval,
).start()
def update(self, args):
time = float(args['time'])
if time > self.maxval:
time = self.maxval
self.pbar.update(time)
@staticmethod
def time_to_secs(duration, total=0):
total = 0
hours, mins, secs = duration.split(':')
total += int(hours) * 3600
total += int(mins) * 60
total += float(secs)
return total
@property
def duration(self):
cmd = '/usr/bin/ffmpeg -i "%s"' % (self.filename)
pipe = subprocess.Popen(
shlex.split(cmd),
stderr=subprocess.PIPE,
close_fds=True
)
chunk = pipe.stderr.read()
duration = re.search(r'Duration: (?P<duration>\S+),', chunk)
if duration:
return self.time_to_secs(duration.group('duration'))
return None
def encode(filename, callback=None):
cmd = 'ffmpeg -i "%s" -acodec libfaac -ab 128kb ' + \
'-vcodec mpeg4 -b 1200kb -mbd 2 -flags +4mv ' + \
'-trellis 2 -cmp 2 -subcmp 2 -s 320x180 "%s.mp4"'
pipe = subprocess.Popen(
shlex.split(cmd % (filename, os.path.splitext(filename)[0])),
stderr=subprocess.PIPE,
close_fds=True
)
fcntl.fcntl(
pipe.stderr.fileno(),
fcntl.F_SETFL,
fcntl.fcntl(pipe.stderr.fileno(), fcntl.F_GETFL) | os.O_NONBLOCK,
)
# frame= 29 fps= 0 q=2.6 size= 114kB time=0.79 bitrate=1181.0kbits/s
reo = re.compile(r"""\S+\s+(?P<frame>\d+) # frame
\s\S+\s+(?P<fps>\d+) # fps
\sq=(?P<q>\S+) # q
\s\S+\s+(?P<size>\S+) # size
\stime=(?P<time>\S+) # time
\sbitrate=(?P<bitrate>[\d\.]+) # bitrate
""", re.X)
while True:
readx = select.select([pipe.stderr.fileno()], [], [])[0]
if readx:
chunk = pipe.stderr.read()
if chunk == '':
break
m = reo.match(chunk)
if m and callback:
callback(m.groupdict())
time.sleep(.1)
if __name__ == '__main__':
parser = optparse.OptionParser()
(options, args) = parser.parse_args()
for arg in args:
root, ext = os.path.splitext(arg)
if os.path.exists(root + '.mp4'):
val = raw_input('File exists. Overwrite [N/y]: ')
if val != 'y':
sys.exit(1)
os.unlink(root + '.mp4')
pbar = EncodingProgressBar(arg)
encode(arg, pbar.update)
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment