import math import collections import string from ..filters import FFmpegGraph, FFmpegChain, FFmpegFilter from .base import OBSSource IDENTIFY_MAPPING = collections.defaultdict(lambda: '_', {ord(k): k for k in string.ascii_letters + string.digits}) def identifiery(n): return n.translate(IDENTIFY_MAPPING) def deg2rad(n): return n * (math.pi / 180) @OBSSource.type('scene') class OBSSceneSource(OBSSource): def __init__(self, *args, **kwargs): super().__init__(*args, **kwargs) self.name = None self.items = [] def load(self, data): self.name = data['name'] self.items = data['settings']['items'] def to_ffmpeg(self, scene): prefix = identifiery(self.name) i = 1 graph = [FFmpegChain( FFmpegFilter('color', c='black', s='{}x{}'.format(*scene.dimensions), outs=[prefix + str(i)]) )] runners = [] for item in self.items: if not item['visible']: continue rs, chains = scene.sources[item['name']].to_ffmpeg(scene) runners.extend(rs) c = chains[-1] if item['scale']['x'] != 1.0 or item['scale']['y'] != 1.0: c.append(FFmpegFilter('scale', w='{} * in_w'.format(item['scale']['x']), h='{} * in_h'.format(item['scale']['y']) )) if item['crop_top'] != 0 or item['crop_bottom'] != 0 or item['crop_left'] or item['crop_right'] != 0: c.append(FFmpegFilter('crop', w='in_w - {} - {}'.format(item['crop_left'], item['crop_right']), h='in_h - {} - {}'.format(item['crop_top'], item['crop_bottom']), x=item['crop_left'], y=item['crop_top'] )) if item['rot'] != 0.0: c.append(FFmpegFilter('rotate', angle=deg2rad(item['rot']) )) c.append(FFmpegFilter('overlay', eval='init', x=item['pos']['x'], y=item['pos']['y'], ins=[prefix + str(i)], outs=[prefix + str(i + 1)]) ) i += 1 graph.extend(chains) return runners, graph