fully implement browser_source
This commit is contained in:
parent
46abaf0a70
commit
d759f5870e
|
@ -25,6 +25,7 @@ CHROMIUM_ARGS = {
|
|||
'use-mock-keychain',
|
||||
'password-store=basic',
|
||||
'incognito',
|
||||
'force-device-scale-factor=1',
|
||||
}
|
||||
CHROMIUM_ENABLES = {
|
||||
'automation',
|
||||
|
|
|
@ -3,40 +3,62 @@ import os
|
|||
import tempfile
|
||||
import shutil
|
||||
import base64
|
||||
import functools
|
||||
|
||||
import trio
|
||||
from trio_cdp import page, emulation, dom
|
||||
|
||||
from ..chromium import Chromium
|
||||
from ..filters import FFmpegChain, FFmpegFilter
|
||||
from ..filters import FFmpegInput, FFmpegChain, FFmpegFilter
|
||||
from .base import OBSSource
|
||||
|
||||
|
||||
async def do_screencast(url, outfile, dims):
|
||||
c = Chromium()
|
||||
async with await c.connect() as conn, await c.select(conn) as sess, sess.page_enable():
|
||||
# Set viewport size and transparency.
|
||||
await emulation.set_device_metrics_override(
|
||||
width=dims[0], height=dims[1],
|
||||
device_scale_factor=1.0, mobile=False
|
||||
)
|
||||
await emulation.set_default_background_color_override(dom.RGBA(0, 0, 0, 0))
|
||||
class BrowserCapturer:
|
||||
def __init__(self, url, outfile, dimensions, rate=25):
|
||||
self.chromium = Chromium()
|
||||
self.url = url
|
||||
self.frame = b''
|
||||
self.outfile = outfile
|
||||
self.dimensions = dimensions
|
||||
self.rate = rate
|
||||
|
||||
# Navigate to the website.
|
||||
async with sess.wait_for(page.LoadEventFired):
|
||||
await page.navigate(url)
|
||||
def run(self):
|
||||
trio.run(self.do_run, restrict_keyboard_interrupt_to_checkpoints=True)
|
||||
|
||||
# Start capture.
|
||||
await page.start_screencast(format_='jpeg', quality=60)
|
||||
async for frame in sess.listen(page.ScreencastFrame):
|
||||
outfile.write(base64.b64decode(frame.data))
|
||||
await page.screencast_frame_ack(frame.session_id)
|
||||
async def do_run(self):
|
||||
async with trio.open_nursery() as nursery:
|
||||
nursery.start_soon(self.capture_frames)
|
||||
nursery.start_soon(self.output_frames)
|
||||
|
||||
def capture_page(url, outfile, dims=(1280, 720)):
|
||||
trio.run(do_screencast, url, outfile, dims, restrict_keyboard_interrupt_to_checkpoints=True)
|
||||
async def capture_frames(self):
|
||||
async with await self.chromium.connect() as conn, await self.chromium.select(conn) as sess, sess.page_enable():
|
||||
# Set viewport size and transparency.
|
||||
await emulation.set_device_metrics_override(
|
||||
width=self.dimensions[0], height=self.dimensions[1],
|
||||
device_scale_factor=1.0, mobile=False
|
||||
)
|
||||
await emulation.set_default_background_color_override(dom.RGBA(0, 0, 0, 0))
|
||||
|
||||
# Navigate to the website.
|
||||
async with sess.wait_for(page.LoadEventFired):
|
||||
await page.navigate(self.url)
|
||||
|
||||
# Start capture.
|
||||
await page.start_screencast(format_='png')
|
||||
async for frame in sess.listen(page.ScreencastFrame):
|
||||
self.frame = base64.b64decode(frame.data)
|
||||
await page.screencast_frame_ack(frame.session_id)
|
||||
|
||||
async def output_frames(self):
|
||||
async with await trio.open_file(self.outfile, 'wb') as f:
|
||||
while True:
|
||||
t = trio.current_time()
|
||||
if self.frame:
|
||||
await f.write(self.frame)
|
||||
await trio.sleep_until(t + 1.0 / self.rate)
|
||||
|
||||
|
||||
@OBSSource.type('browser')
|
||||
@OBSSource.type('browser_source')
|
||||
class OBSBrowserSource(OBSSource):
|
||||
def __init__(self, *args, **kwargs):
|
||||
super().__init__(*args, **kwargs)
|
||||
|
@ -52,20 +74,21 @@ class OBSBrowserSource(OBSSource):
|
|||
|
||||
def load(self, data):
|
||||
self.name = data['name']
|
||||
self.local = data['settings']['is_local_file']
|
||||
self.local = data['settings'].get('is_local_file', False)
|
||||
if self.local:
|
||||
self.url = data['settings']['local_file']
|
||||
else:
|
||||
self.url = data['settings']['url']
|
||||
self.width = data['settings']['width']
|
||||
self.height = data['settings']['height']
|
||||
self.audio = data['settings']['reroute_audio']
|
||||
self.audio = data['settings'].get('reroute_audio', False)
|
||||
|
||||
def to_ffmpeg(self, scene):
|
||||
fifo_path = os.path.join(self.tempdir, 'frame.bin')
|
||||
fifo = os.mkfifo(fifo_path)
|
||||
runner = functools.partial(capture_page, url=self.url, outfile=fifo_path, dims=(self.width, self.height))
|
||||
os.mkfifo(fifo_path)
|
||||
print(self.width, self.height)
|
||||
runner = BrowserCapturer(self.url, fifo_path, dimensions=(self.width, self.height))
|
||||
return [FFmpegChain(
|
||||
inputs=[FFmpegInput(fifo_path, f='image2pipe', framerate=runner.rate, follow=1, probesize=8192)],
|
||||
runners=[runner]
|
||||
runners=[runner.run]
|
||||
)]
|
||||
|
|
Loading…
Reference in New Issue