Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Chromium recording #9174

Merged
merged 2 commits into from
Jul 10, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
8 changes: 8 additions & 0 deletions recording/server.conf.in
Original file line number Diff line number Diff line change
Expand Up @@ -109,3 +109,11 @@

# The extension of the file for audio and video recordings.
#extensionvideo = .webm

[recording]
# Browser to use for recordings. Please note that the "chrome" value does not
# refer to the web browser, but to the Selenium WebDriver. In practice, "chrome"
# will use Google Chrome, or Chromium if Google Chrome is not installed.
# Allowed values: firefox, chrome
# Defaults to firefox
# browser = firefox
9 changes: 9 additions & 0 deletions recording/src/nextcloud/talk/recording/Config.py
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
#
# @copyright Copyright (c) 2023, Daniel Calviño Sánchez ([email protected])
# @copyright Copyright (c) 2023, Elmer Miroslav Mosher Golovin ([email protected])
#
# @license GNU AGPL version 3 or any later version
#
Expand Down Expand Up @@ -236,4 +237,12 @@ def getFfmpegExtensionVideo(self):
"""
return self._configParser.get('ffmpeg', 'extensionvideo', fallback='.webm')

def getBrowserForRecording(self):
"""
Returns the browser identifier that will be used for recordings.

Defaults to "firefox".
"""
return self._configParser.get('recording', 'browser', fallback='firefox')

danxuliu marked this conversation as resolved.
Show resolved Hide resolved
config = Config()
59 changes: 56 additions & 3 deletions recording/src/nextcloud/talk/recording/Participant.py
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
#
# @copyright Copyright (c) 2023, Daniel Calviño Sánchez ([email protected])
# @copyright Copyright (c) 2023, Elmer Miroslav Mosher Golovin ([email protected])
#
# @license GNU AGPL version 3 or any later version
#
Expand Down Expand Up @@ -33,7 +34,12 @@
from secrets import token_urlsafe
from selenium import webdriver
from selenium.webdriver.common.by import By
from selenium.webdriver.chrome.options import Options as ChromeOptions
from selenium.webdriver.chrome.service import Service as ChromeService
from selenium.webdriver.chrome.webdriver import WebDriver as ChromeDriver
from selenium.webdriver.firefox.options import Options as FirefoxOptions
from selenium.webdriver.firefox.service import Service as FirefoxService
from selenium.webdriver.firefox.webdriver import WebDriver as FirefoxDriver
from selenium.webdriver.support.wait import WebDriverWait
from shutil import disk_usage
from time import sleep
Expand Down Expand Up @@ -202,6 +208,51 @@ def __del__(self):
# created in "/tmp".
self.driver.quit()

def startChrome(self, width, height, env):
"""
Starts a Chrome instance.

Will use Chromium if Google Chrome is not installed.

:param width: the width of the browser window.
:param height: the height of the browser window.
:param env: the environment variables, including the display to start
the browser in.
"""

options = ChromeOptions()

# "webSocketUrl" is needed for BiDi.
options.set_capability('webSocketUrl', True)

options.add_argument('--use-fake-ui-for-media-stream')

# Allow to play media without user interaction.
options.add_argument('--autoplay-policy=no-user-gesture-required')

options.add_argument('--kiosk')
options.add_argument(f'--window-size={width},{height}')
options.add_argument('--disable-infobars')
danxuliu marked this conversation as resolved.
Show resolved Hide resolved
options.add_experimental_option("excludeSwitches", ["enable-automation"])

if disk_usage('/dev/shm').free < 2147483648:
self._logger.info('Less than 2 GiB available in "/dev/shm", usage disabled')
options.add_argument("--disable-dev-shm-usage")

if disk_usage('/tmp').free < 134217728:
self._logger.warning('Less than 128 MiB available in "/tmp", strange failures may occur')

service = ChromeService(
env=env,
)

self.driver = ChromeDriver(
options=options,
service=service,
)

self.bidiLogsHelper = BiDiLogsHelper(self.driver, self._parentLogger)
danxuliu marked this conversation as resolved.
Show resolved Hide resolved

def startFirefox(self, width, height, env):
"""
Starts a Firefox instance.
Expand All @@ -212,7 +263,7 @@ def startFirefox(self, width, height, env):
the browser in.
"""

options = webdriver.FirefoxOptions()
options = FirefoxOptions()

# "webSocketUrl" is needed for BiDi; this should be set already by
# default, but just in case.
Expand All @@ -239,7 +290,7 @@ def startFirefox(self, width, height, env):
env=env,
)

self.driver = webdriver.Firefox(
self.driver = FirefoxDriver(
options=options,
service=service,
)
Expand Down Expand Up @@ -418,7 +469,9 @@ def __init__(self, browser, nextcloudUrl, width, height, env, parentLogger):

self.seleniumHelper = SeleniumHelper(parentLogger)

if browser == 'firefox':
if browser == 'chrome':
self.seleniumHelper.startChrome(width, height, env)
elif browser == 'firefox':
self.seleniumHelper.startFirefox(width, height, env)
else:
raise Exception('Invalid browser: ' + browser)
Expand Down
5 changes: 4 additions & 1 deletion recording/src/nextcloud/talk/recording/Service.py
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
#
# @copyright Copyright (c) 2023, Daniel Calviño Sánchez ([email protected])
# @copyright Copyright (c) 2023, Elmer Miroslav Mosher Golovin ([email protected])
#
# @license GNU AGPL version 3 or any later version
#
Expand Down Expand Up @@ -188,8 +189,10 @@ def start(self, actorType, actorId):
env = self._display.env()
env['PULSE_SINK'] = audioSinkIndex

browser = config.getBrowserForRecording()

self._logger.debug("Starting participant")
self._participant = Participant('firefox', self.backend, width, height, env, self._logger)
self._participant = Participant(browser, self.backend, width, height, env, self._logger)

self._logger.debug("Joining call")
self._participant.joinCall(self.token)
Expand Down