#!/usr/bin/python # # flufigut # # flufigut, the flumotion configuration utility, is a simple tool # that generates flumotion configuration files using pyhton jinja2 # template engine and simplejson. flufigut generates planet.xml # and worker.xml files from configuration templates and an easy to # understand representation of the flow structure written in json. # # # Copyright (C) 2012 Christian Pointner # Michael Gebetsroither # # This file is part of flufigut. # # flufigut is free software: you can redistribute it and/or modify # it under the terms of the GNU General Public License as published by # the Free Software Foundation, either version 2 of the License, or # any later version. # # flufigut is distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY; without even the implied warranty of # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the # GNU General Public License for more details. # # You should have received a copy of the GNU General Public License # along with flufigut. If not, see . # import string import random import sys import simplejson as json from exceptions import * from jinja2 import Environment, FileSystemLoader ### helper functions ############################################ # def rand_string(size=8, chars=string.ascii_lowercase + string.ascii_uppercase + string.digits): return ''.join(random.choice(chars) for x in range(size)) ### parse json file ############################################# # if len(sys.argv) <= 2: raise SystemExit("No template name and or configuration file given") cf = open(sys.argv[2], 'r') config = json.load(cf); cf.close(); ### initialization ############################################## # atmosphere = {} flow = {} machines = {} globals = config['globals'] input = config['input'] transcode = config['transcode'] stream = config['stream'] ### generate porter for all streamer/machines ################### # idx = 0 for streamer in stream: worker = 'streamer%i'%(idx) port = streamer['config']['port'] found = False for machine in globals['machines'].keys(): if worker in globals['machines'][machine]: if machine in machines: if 'porter' in machines[machine]: if port in machines[machine]['porter']: print "Porter: machine %s already uses port %i" % (machine, port) sys.exit(1) else: machines[machine]['porter'] = {} else: machines[machine] = { 'porter': {} } found = True machines[machine]['porter'][port] = { 'socket-path': "porter%i-%s"%(idx, rand_string()), 'username': rand_string(size=12), 'password': rand_string(size=12), } atmosphere['porter-%s-%i'%(machine, port)] = { 'type': "porter", 'desc': "Porter for %s on port %i"%(machine, port), 'worker': worker, 'properties': { 'port': port, 'socket-path': machines[machine]['porter'][port]['socket-path'], 'username': machines[machine]['porter'][port]['username'], 'password': machines[machine]['porter'][port]['password'], }, } if not found: print "Streamer %i has no machine assigned" % (idx) sys.exit(1) idx+=1 ### generate input components ################################### flow['input'] = {} flow['input']['raw-input'] = { 'type': input['source'], 'desc': "capture raw AV from %s" % input['source'], 'worker': 'input', 'properties': {}, } for property in input.keys(): if property == 'samplerate': flow['input']['raw-input']['properties'][property] = input['samplerate'] elif property == 'resolution': flow['input']['raw-input']['properties']['width'] = globals['resolutions'][input[property]]['width'] flow['input']['raw-input']['properties']['height'] = globals['resolutions'][input[property]]['height'] flow['input']['raw-input']['properties']['framerate'] = globals['resolutions'][input[property]]['rate'] elif property != 'source': flow['input']['raw-input']['properties'][property] = input[property] samplerates = [ ] resolutions = [ ] for format in transcode.keys(): if 'samplerate' in globals['formats'][format]: samplerate = globals['formats'][format]['samplerate'] if samplerate not in samplerates: if input['samplerate'] != samplerate: samplerates.append(samplerate) for profile in transcode[format]: resolution = globals['profiles'][profile]['video'] if resolution not in resolutions: if input['resolution'] != resolution: if globals['resolutions'][resolution]['rate'] != globals['resolutions'][input['resolution']]['rate']: print "video rate conversion is not yet supported!!!" sys.exit(-1) resolutions.append(resolution) for resolution in resolutions: flow['input']['resize-%s' % resolution] = { 'type': 'video-resize', 'desc': "resize video to %sx%s" % (globals['resolutions'][resolution]['width'], globals['resolutions'][resolution]['height']), 'worker': 'input', 'feeder': 'raw-input:video', 'properties': { 'width': globals['resolutions'][resolution]['width'], 'height': globals['resolutions'][resolution]['height'], }, } for samplerate in samplerates: flow['input']['resample-%s' % samplerate] = { 'type': 'audio-resample', 'desc': "resample audio to %s Hz" % samplerate, 'worker': 'input', 'feeder': 'raw-input:audio', 'properties': { 'samplerate': samplerate, }, } ### generate encoder and muxer components ####################### flow['encoder_video'] = {} flow['encoder_audio'] = {} flow['muxer'] = {} for format in transcode.keys(): for profile in transcode[format]: video_encoder = 'none' if 'video' in globals['formats'][format]: encoder = globals['formats'][format]['video'] resolution = globals['profiles'][profile]['video'] bitrate = globals['bitrates'][encoder][resolution] if resolution == input['resolution']: feeder = 'raw-input:video' else: feeder = 'resize-%s' % resolution video_encoder = 'encode-%s-%s' % (encoder, resolution) if video_encoder not in flow['encoder_video'].keys(): flow['encoder_video'][video_encoder] = { 'type': '%s-encode' % encoder, 'desc': "%s encoder for %sx%s" % (encoder, globals['resolutions'][resolution]['width'], globals['resolutions'][resolution]['height']), 'worker': 'encoder-%s' % encoder, 'feeder': feeder, 'properties': { 'bitrate': bitrate, }, } audio_encoder = 'none' if 'audio' in globals['formats'][format]: encoder = globals['formats'][format]['audio'] bitrate = globals['profiles'][profile]['audio'] if 'samplerate' in globals['formats'][format]: samplerate = globals['formats'][format]['samplerate'] feeder = 'resample-%s' % samplerate else: samplerate = input['samplerate'] feeder = 'raw-input:audio' audio_encoder = 'encode-%s-%i-%i' % (encoder, bitrate, samplerate) if audio_encoder not in flow['encoder_audio']: flow['encoder_audio'][audio_encoder] = { 'type': '%s-encode' % encoder, 'desc': "%s encoder for %i kbit/s @ %i Hz" % (encoder, bitrate, samplerate), 'worker': 'encoder-%s' % encoder, 'feeder': feeder, 'properties': { 'bitrate': bitrate, }, } muxer = globals['formats'][format]['muxer'] flow['muxer']['muxer-%s-%s' % (muxer, profile)] = { 'type': '%s-mux' % muxer, 'desc': "%s muxer profile %s" % (format, profile), 'worker': 'muxer-%s' % muxer, 'feeder_audio': audio_encoder, 'feeder_video': video_encoder, 'properties': {}, } ### generate streamer components ################################ flow['streamer'] = {} # TODO ### initialize and render templates ############################# # env = Environment(loader=FileSystemLoader('../templates/%s/' % (sys.argv[1])), line_statement_prefix = '%%') template = env.get_template('planet.xml') planet = template.render(globals=globals, atmosphere=atmosphere, flow=flow) sys.stdout.write(planet.encode("utf8")) ### end #########################################################