hemisphere/src/overlay/obs/scene.py

76 lines
2.4 KiB
Python

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 = 0
graph = [FFmpegChain(
FFmpegFilter('color', c='black', s='{}x{}'.format(*scene.dimensions), outs=[prefix + str(0)])
)]
i += 1
for item in self.items:
if not item['visible']:
continue
chains = scene.sources[item['name']].to_ffmpeg(scene)
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'])
))
if not c[-1].outs:
c[-1].outs.append(prefix + 'Out' + str(i))
chains.append(FFmpegChain(
FFmpegFilter('overlay',
eval='init',
x=item['pos']['x'],
y=item['pos']['y'],
ins=[prefix + str(i - 1), c[-1].outs[-1]],
outs=[prefix + str(i)]
)
))
i += 1
graph.extend(chains)
return graph