implement text support

This commit is contained in:
Shiz 2020-05-20 00:21:35 +02:00
parent f926b94c99
commit cb210fcc3e
7 changed files with 37 additions and 24 deletions

View File

@ -50,10 +50,11 @@ class FFmpegFilter:
) )
class FFmpegChain: class FFmpegChain:
def __init__(self, *filters, inputs=None, runners=None): def __init__(self, *filters, inputs=None, runners=None, overlay=True):
self.filters = list(filters) self.filters = list(filters)
self.inputs = inputs or [] self.inputs = inputs or []
self.runners = runners or [] self.runners = runners or []
self.overlay = overlay
def append(self, f): def append(self, f):
self.filters.append(f) self.filters.append(f)

View File

@ -67,7 +67,7 @@ class OBSSource:
def load(self, data): def load(self, data):
raise NotImplementedError raise NotImplementedError
def to_ffmpeg(self, scene): def to_ffmpeg(self, scene, item):
raise NotImplementedError raise NotImplementedError
@classmethod @classmethod
@ -105,9 +105,9 @@ class OBSScene:
for src in data['sources']: for src in data['sources']:
self.sources[src['name']] = OBSSource.find_and_load(src) self.sources[src['name']] = OBSSource.find_and_load(src)
def to_ffmpeg(self, scene=None): def to_ffmpeg(self, scene=None, item=None):
scene = scene or self.current_scene scene = scene or self.current_scene
chains = self.sources[scene].to_ffmpeg(self) chains = self.sources[scene].to_ffmpeg(self, item)
r = FFmpegGraph() r = FFmpegGraph()
r.extend(chains) r.extend(chains)

View File

@ -107,7 +107,7 @@ class OBSBrowserSource(OBSSource):
self.height = data['settings']['height'] self.height = data['settings']['height']
self.audio = data['settings'].get('reroute_audio', False) self.audio = data['settings'].get('reroute_audio', False)
def to_ffmpeg(self, scene): def to_ffmpeg(self, scene, item):
fifo_path = os.path.join(self.tempdir, 'frame.bin') fifo_path = os.path.join(self.tempdir, 'frame.bin')
os.mkfifo(fifo_path) os.mkfifo(fifo_path)

View File

@ -105,7 +105,7 @@ class OBSBrowserSource(OBSSource):
self.height = data['settings']['height'] self.height = data['settings']['height']
self.audio = data['settings'].get('reroute_audio', False) self.audio = data['settings'].get('reroute_audio', False)
def to_ffmpeg(self, scene): def to_ffmpeg(self, scene, item):
fifo_path = os.path.join(self.tempdir, 'frame.bin') fifo_path = os.path.join(self.tempdir, 'frame.bin')
os.mkfifo(fifo_path) os.mkfifo(fifo_path)

View File

@ -26,7 +26,7 @@ class OBSSceneSource(OBSSource):
self.name = data['name'] self.name = data['name']
self.items = data['settings']['items'] self.items = data['settings']['items']
def to_ffmpeg(self, scene): def to_ffmpeg(self, scene, item):
prefix = identifiery(self.name) prefix = identifiery(self.name)
i = 0 i = 0
graph = [FFmpegChain( graph = [FFmpegChain(
@ -38,7 +38,7 @@ class OBSSceneSource(OBSSource):
if not item['visible']: if not item['visible']:
continue continue
chains = scene.sources[item['name']].to_ffmpeg(scene) chains = scene.sources[item['name']].to_ffmpeg(scene, item)
c = chains[-1] c = chains[-1]
if item['scale']['x'] != 1.0 or item['scale']['y'] != 1.0: if item['scale']['x'] != 1.0 or item['scale']['y'] != 1.0:
@ -59,15 +59,18 @@ class OBSSceneSource(OBSSource):
)) ))
if not c[-1].outs: if not c[-1].outs:
c[-1].outs.append(prefix + 'Out' + str(i)) c[-1].outs.append(prefix + 'Out' + str(i))
chains.append(FFmpegChain( if c.overlay:
FFmpegFilter('overlay', chains.append(FFmpegChain(
eval='init', FFmpegFilter('overlay',
x=item['pos']['x'], eval='init',
y=item['pos']['y'], x=item['pos']['x'],
ins=[prefix + str(i - 1), c[-1].outs[-1]], y=item['pos']['y'],
outs=[prefix + str(i)] ins=[prefix + str(i - 1), c[-1].outs[-1]],
) outs=[prefix + str(i)]
)) )
))
else:
c[0].ins.append(prefix + str(i - 1))
i += 1 i += 1
graph.extend(chains) graph.extend(chains)

View File

@ -12,17 +12,21 @@ class TextSource(OBSSource):
self.shadow = 0 self.shadow = 0
self.shadow_color = '#000000' self.shadow_color = '#000000'
def to_ffmpeg(self, scene): def to_ffmpeg(self, scene, item):
return [FFmpegChain( return [FFmpegChain(
FFmpegFilter('drawtext', FFmpegFilter('drawtext',
expansion='none', expansion='none',
fontcolor=self.color, fontcolor=hex(self.color),
font=self.font, font=self.font,
fontsize=self.size,
text=self.contents, text=self.contents,
shadowcolor=self.shadow_color, shadowcolor=self.shadow_color,
shadowx=self.shadow, shadowx=self.shadow,
shadowy=self.shadow, shadowy=self.shadow,
) x=item['pos']['x'],
y=item['pos']['y'],
),
overlay=False
)] )]
@OBSSource.type('text_gdiplus') @OBSSource.type('text_gdiplus')
@ -32,9 +36,14 @@ class GDIPlusSource(TextSource):
self.size = data['settings']['font']['size'] self.size = data['settings']['font']['size']
self.color = data['settings']['color'] self.color = data['settings']['color']
import struct
def swap32(i):
return struct.unpack("<I", struct.pack(">I", i))[0]
@OBSSource.type('text_ft2_source') @OBSSource.type('text_ft2_source')
class FreeType2Source(TextSource): class FreeType2Source(TextSource):
def load(self, data): def load(self, data):
self.font = data['settings']['font']['face'] self.font = data['settings']['font']['face'] + ((' ' + data['settings']['font']['style']) if data['settings']['font'].get('style') else '')
self.size = data['settings']['font']['size'] self.size = data['settings']['font']['size']
self.color = data['settings']['color0'] self.color = swap32(data['settings']['color1'])
self.contents = data['settings']['text']

View File

@ -11,7 +11,7 @@ class ImageSource(OBSSource):
def load(self, data): def load(self, data):
self.infile = data['settings']['file'] self.infile = data['settings']['file']
def to_ffmpeg(self, scene): def to_ffmpeg(self, scene, item):
return [FFmpegChain(inputs=[FFmpegInput(self.infile)])] return [FFmpegChain(inputs=[FFmpegInput(self.infile)])]
@OBSSource.type('ffmpeg_source') @OBSSource.type('ffmpeg_source')
@ -25,7 +25,7 @@ class FFmpegSource(OBSSource):
self.infile = data['settings']['local_file'] self.infile = data['settings']['local_file']
self.loop = data['settings']['looping'] self.loop = data['settings']['looping']
def to_ffmpeg(self, scene): def to_ffmpeg(self, scene, item):
return [FFmpegChain( return [FFmpegChain(
inputs=[FFmpegInput(self.infile, re=None, stream_loop=-1 if self.loop else 0)] inputs=[FFmpegInput(self.infile, re=None, stream_loop=-1 if self.loop else 0)]
)] )]