implement text support
This commit is contained in:
parent
f926b94c99
commit
cb210fcc3e
|
@ -50,10 +50,11 @@ class FFmpegFilter:
|
|||
)
|
||||
|
||||
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.inputs = inputs or []
|
||||
self.runners = runners or []
|
||||
self.overlay = overlay
|
||||
|
||||
def append(self, f):
|
||||
self.filters.append(f)
|
||||
|
|
|
@ -67,7 +67,7 @@ class OBSSource:
|
|||
def load(self, data):
|
||||
raise NotImplementedError
|
||||
|
||||
def to_ffmpeg(self, scene):
|
||||
def to_ffmpeg(self, scene, item):
|
||||
raise NotImplementedError
|
||||
|
||||
@classmethod
|
||||
|
@ -105,9 +105,9 @@ class OBSScene:
|
|||
for src in data['sources']:
|
||||
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
|
||||
chains = self.sources[scene].to_ffmpeg(self)
|
||||
chains = self.sources[scene].to_ffmpeg(self, item)
|
||||
|
||||
r = FFmpegGraph()
|
||||
r.extend(chains)
|
||||
|
|
|
@ -107,7 +107,7 @@ class OBSBrowserSource(OBSSource):
|
|||
self.height = data['settings']['height']
|
||||
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')
|
||||
os.mkfifo(fifo_path)
|
||||
|
||||
|
|
|
@ -105,7 +105,7 @@ class OBSBrowserSource(OBSSource):
|
|||
self.height = data['settings']['height']
|
||||
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')
|
||||
os.mkfifo(fifo_path)
|
||||
|
||||
|
|
|
@ -26,7 +26,7 @@ class OBSSceneSource(OBSSource):
|
|||
self.name = data['name']
|
||||
self.items = data['settings']['items']
|
||||
|
||||
def to_ffmpeg(self, scene):
|
||||
def to_ffmpeg(self, scene, item):
|
||||
prefix = identifiery(self.name)
|
||||
i = 0
|
||||
graph = [FFmpegChain(
|
||||
|
@ -38,7 +38,7 @@ class OBSSceneSource(OBSSource):
|
|||
if not item['visible']:
|
||||
continue
|
||||
|
||||
chains = scene.sources[item['name']].to_ffmpeg(scene)
|
||||
chains = scene.sources[item['name']].to_ffmpeg(scene, item)
|
||||
c = chains[-1]
|
||||
|
||||
if item['scale']['x'] != 1.0 or item['scale']['y'] != 1.0:
|
||||
|
@ -59,15 +59,18 @@ class OBSSceneSource(OBSSource):
|
|||
))
|
||||
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)]
|
||||
)
|
||||
))
|
||||
if c.overlay:
|
||||
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)]
|
||||
)
|
||||
))
|
||||
else:
|
||||
c[0].ins.append(prefix + str(i - 1))
|
||||
i += 1
|
||||
|
||||
graph.extend(chains)
|
||||
|
|
|
@ -12,17 +12,21 @@ class TextSource(OBSSource):
|
|||
self.shadow = 0
|
||||
self.shadow_color = '#000000'
|
||||
|
||||
def to_ffmpeg(self, scene):
|
||||
def to_ffmpeg(self, scene, item):
|
||||
return [FFmpegChain(
|
||||
FFmpegFilter('drawtext',
|
||||
expansion='none',
|
||||
fontcolor=self.color,
|
||||
fontcolor=hex(self.color),
|
||||
font=self.font,
|
||||
fontsize=self.size,
|
||||
text=self.contents,
|
||||
shadowcolor=self.shadow_color,
|
||||
shadowx=self.shadow,
|
||||
shadowy=self.shadow,
|
||||
)
|
||||
x=item['pos']['x'],
|
||||
y=item['pos']['y'],
|
||||
),
|
||||
overlay=False
|
||||
)]
|
||||
|
||||
@OBSSource.type('text_gdiplus')
|
||||
|
@ -32,9 +36,14 @@ class GDIPlusSource(TextSource):
|
|||
self.size = data['settings']['font']['size']
|
||||
self.color = data['settings']['color']
|
||||
|
||||
import struct
|
||||
def swap32(i):
|
||||
return struct.unpack("<I", struct.pack(">I", i))[0]
|
||||
|
||||
@OBSSource.type('text_ft2_source')
|
||||
class FreeType2Source(TextSource):
|
||||
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.color = data['settings']['color0']
|
||||
self.color = swap32(data['settings']['color1'])
|
||||
self.contents = data['settings']['text']
|
||||
|
|
|
@ -11,7 +11,7 @@ class ImageSource(OBSSource):
|
|||
def load(self, data):
|
||||
self.infile = data['settings']['file']
|
||||
|
||||
def to_ffmpeg(self, scene):
|
||||
def to_ffmpeg(self, scene, item):
|
||||
return [FFmpegChain(inputs=[FFmpegInput(self.infile)])]
|
||||
|
||||
@OBSSource.type('ffmpeg_source')
|
||||
|
@ -25,7 +25,7 @@ class FFmpegSource(OBSSource):
|
|||
self.infile = data['settings']['local_file']
|
||||
self.loop = data['settings']['looping']
|
||||
|
||||
def to_ffmpeg(self, scene):
|
||||
def to_ffmpeg(self, scene, item):
|
||||
return [FFmpegChain(
|
||||
inputs=[FFmpegInput(self.infile, re=None, stream_loop=-1 if self.loop else 0)]
|
||||
)]
|
||||
|
|
Loading…
Reference in New Issue