oxdbarchive/oxdbarchive/tools/extract_timeline.py

122 lines
3.5 KiB
Python

#!/usr/bin/env python
# -*- Mode: Python; -*-
# -*- coding: utf-8 -*-
# vi:si:et:sw=2:sts=2:ts=2
import gobject
gobject.threads_init()
import pygst
pygst.require('0.10')
import gst
import Image
import sys, os, shutil, time
from glob import glob
import math
bar_part_time = 60 * 10
bar_height = 16
class GstTimeline:
def __init__(self, timeline_png):
self.timeline_png = timeline_png
self.bar = None
self.frames = 0
self.length = 0
self.number_of_frames = 0
def addVideo(self, video_file):
s = ''' filesrc name=input
! decodebin name=dbin
! queue name =q
! ffmpegcolorspace ! video/x-raw-rgb
! fakesink name=output signal-handoffs=true
'''
self.pipeline = gst.parse_launch(s)
self.input = self.pipeline.get_by_name('input')
self.fakesink = self.pipeline.get_by_name('output')
self.dbin = self.pipeline.get_by_name('dbin')
self.bus = self.pipeline.get_bus()
self.input.set_property("location", video_file)
self.pipeline.set_state(gst.STATE_PAUSED)
self.pipeline.get_state()
#length
queue = self.pipeline.get_by_name('q')
pads = queue.sink_pads()
q = gst.query_new_duration(gst.FORMAT_TIME)
for pad in pads:
if pad.get_peer() and pad.get_peer().query(q):
format, self.length = q.parse_duration()
seconds = int(math.ceil(float(self.length) / gst.SECOND))
print "seconds", seconds
self.timelineImage = Image.new("RGB", (seconds, bar_height))
self.timelineImagePos = 0
#extract frames
ho = self.fakesink.connect ("handoff", self.snapshot_png_handoff_cb)
self.pipeline.set_state(gst.STATE_PLAYING)
self.pipeline.get_state()
while 1:
msg = self.bus.poll(gst.MESSAGE_EOS | gst.MESSAGE_ERROR, gst.SECOND)
if msg:
break
self.fakesink.disconnect(ho)
self.pipeline.set_state(gst.STATE_NULL)
def cropAndSave(self):
if self.frames:
mini_width = int(self.frames / self.fps)
mini_width = min(mini_width, bar_part_time)
#crop if segment is shorter
c = self.bar.crop((0, 0, self.frames,bar_height))
#resize to 1 pixel per second
mini = c.resize((mini_width,bar_height), Image.ANTIALIAS)
#add to timeline png
self.timelineImage.paste(mini, (self.timelineImagePos, 0))
self.timelineImagePos += mini_width
self.frames = 0
def close(self):
self.cropAndSave()
self.timelineImage.save(self.timeline_png)
def snapshot_png_handoff_cb(self, sink, gst_buffer, pad):
caps = sink.sink_pads().next().get_negotiated_caps()
for s in caps:
input_d = (s['width'], s['height'])
framerate = s['framerate']
if not self.bar:
self.fps = float(framerate.num) / framerate.denom
self.width_part = int(self.fps * bar_part_time)
self.bar = Image.new("RGB", (self.width_part + 1 ,bar_height))
img = Image.fromstring('RGB',input_d, gst_buffer)
height = 16
img = img.resize((1, height), Image.ANTIALIAS)
self.frames += 1
for i in range(height):
self.bar.putpixel((self.frames, i), img.getpixel((0,i)))
if self.frames >= self.width_part and self.frames > 30:
self.cropAndSave()
def usage():
print ""
print "usage: %s output_base_path video_file" % sys.argv[0]
print ""
sys.exit(1)
if __name__ == "__main__":
if len(sys.argv) < 2:
usage()
if not os.path.exists(sys.argv[1]):
print "target does not exist"
sys.exit(1)
g = GstTimeline(sys.argv[1])
g.addVideo(sys.argv[2])
g.close()