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

Add recording server #8708

Merged
merged 20 commits into from Feb 14, 2023
Merged

Add recording server #8708

merged 20 commits into from Feb 14, 2023

Conversation

danxuliu
Copy link
Member

@danxuliu danxuliu commented Feb 5, 2023

Fixes #8521

When a call needs to be started the Nextcloud server sends a request to the recording server. The recording server launches a browser in its own virtual display server and with its own audio device (so several browsers can be running at the same time without interfering with each other), joins the call in that browser and then captures the video and sound of the virtual display and the audio device. Once the recording server receives a request from the Nextcloud server to stop the recording the file is uploaded from the recording server to the Nextcloud server.

Right now, due to the use of a real participant, only public calls can be recorded (because the participant joins as a guest). This will be solved by using an internal client of the signaling server (which will also limit recording the calls only when an external signaling server is configured). Similarly, the recorded call right now shows the standard Talk UI; this will be solved by adding a custom UI for the recording client.

The format of the recording had to be changed from Theora in mkv to VP8 in webm, as Chromium does not play Theora (the Nextcloud viewer shows some of them, though, but I do not know if it provides a built-in codec like Wikipedia, and in any case the recorded ones did not play properly, maybe due to some timestamp issues) and Firefox does not play mkv (although, again, according to the ticket it does in some cases, but at least it did not work with Nextcloud viewer). Unfortunately VP8 seems to require more CPU to be encoded than Theora.

🚧 TODO

  • Unload the audio sink module once the recording ended
  • Recording service helpers may not be stopped in some cases - If a recording is started in the recording server and then stopped again before the recording actually started the service helpers may not be properly stopped in some cases. For example, if the recording is stopped before the virtual display was launched (which would be highly unlikely), as the starting thread would not be aware that the recording is stopped and, therefore, that the virtual display and the rest of the helpers should not be started; if the virtual display was already launched it would be stopped when the recording is stopped, which would implicitly prevent the browser (and probably the recording) from starting. This should not happen if the recording is stopped once it has actually started, so it could be fine to fix this in a follow up pull request. - Recording service helpers may not be stopped in some cases #8750

How to test

[http]
listen = 0.0.0.0:8000

[backend]
allowall = true

secret = the-shared-secret

skipverify = true (if using a self signed certificate in the Nextcloud server)
  • Execute start-container.sh in recording. This will create a Docker container with all the needed dependencies and use the settings just defined for the recording server
  • In Talk settings, set the address of the recording server to http://{IP_ADDRESS}:8000; the IP address can be found with docker inspect talk-recording
  • Start a public call
  • Record it
  • Wait a little after the recording guest joined and then stop the call

Next steps (follow up pull requests)

  • Use an specific UI for the recording client - Add specific UI for recording calls #8725
  • Use an internal client of the signaling server rather than a real participant - Use internal client of signaling server for recording #8756
    • This will make possible to record in calls other than public ones
    • It should also fix stopping recording when last participant leaves
      • It could be done already by the recording client when it detects that it is the last participant, but not worth the effort
  • The recorder needs to be able to notify errors to Nextcloud server, for example if a recording can not be started. Moreover, starting the recording can take some seconds, so it would be better if the UI reflects that the recording started when it actually started. - Change recording status when notified by recording server #8720
  • Make ffmpeg command configurable so it can be adjusted if needed
  • Use a real web server - Flask built-in web server is not recommended in production
  • Brute force protection for recording server
  • Dockerfile to build image rather than installing on the fly. Maybe .deb packages? The recording server requires a lot of dependencies that are not typically installed in a server (like Firefox), so it may be better to install it using a container. On the other hand, the recording server will be likely an isolated server without other services, so it may not be a big problem.
    • ubuntu:20.04 is used for now; using ubuntu:22.04 is tricky, because in 22.04 Firefox became a snap package, and installing snap packages inside a Docker container is not straightforward
    • Check if running Firefox inside a container could prevent accelerated graphics, as that could add a noticeable load in the system
  • Documentation
  • Add endpoint for Prometheus metrics?
  • Move recording server to its own repository once stabilized?

🏁 Checklist

@danxuliu

This comment was marked as resolved.

@nickvergessen

This comment was marked as resolved.

@danxuliu

This comment was marked as resolved.

docs/settings.md Outdated Show resolved Hide resolved
Signed-off-by: Daniel Calviño Sánchez <danxuliu@gmail.com>
"server.conf.in" is provided as an example file with a description of
all the configurations. Some descriptions were copied from
https://github.com/strukturag/nextcloud-spreed-signaling/blob/v1.0.0/server.conf.in,
which is also licensed under the GNU AGPLv3.

Signed-off-by: Daniel Calviño Sánchez <danxuliu@gmail.com>
Based on the real participant class (and related) from
"Talkbuchet-cli.py", but with some adjustments, like using kiosk mode,
loading the browser with specific environment variables (which will make
possible to load the browser in a specific display and to send the audio
to a specific device) or preventing any microphone or camera from being
used.

Signed-off-by: Daniel Calviño Sánchez <danxuliu@gmail.com>
Signed-off-by: Daniel Calviño Sánchez <danxuliu@gmail.com>
To record a call a virtual display server and an audio sink are created.
Then a browser is launched inside the virtual display server, and its
audio is routed to the audio sink. This ensures that several browsers
can be running at the same time without interfering with each other.
Then the call is joined by the browser, and an FFMPEG process to record
the virtual display driver and the audio sink is started.

Once the recording is stopped it is uploaded to the Nextcloud server.

Signed-off-by: Daniel Calviño Sánchez <danxuliu@gmail.com>
Signed-off-by: Daniel Calviño Sánchez <danxuliu@gmail.com>
The script creates a Docker container and installs all the needed
dependencies as well as the recording backend inside it.

Once the container has been created running the script will just launch
the recording backend again in the existing container, without setting
it up.

Note that the configuration (/etc/nextcloud-talk-recording/server.conf)
needs to be customized as needed.

Signed-off-by: Daniel Calviño Sánchez <danxuliu@gmail.com>
Currently the recording server does not support clustering, so the UI is
limited to add a single recording server, even if internally the
configuration allows more than one.

Signed-off-by: Daniel Calviño Sánchez <danxuliu@gmail.com>
Signed-off-by: Daniel Calviño Sánchez <danxuliu@gmail.com>
Signed-off-by: Daniel Calviño Sánchez <danxuliu@gmail.com>
The credentials to be used are specific to the recording server and
unrelated to the SIP bridge. The code follows the same schema used for
validation of external signaling server requests in SignalingController.

Signed-off-by: Daniel Calviño Sánchez <danxuliu@gmail.com>
The owner of the recording must be provided when starting it to be able
to later store it.

Signed-off-by: Daniel Calviño Sánchez <danxuliu@gmail.com>
Signed-off-by: Daniel Calviño Sánchez <danxuliu@gmail.com>
Chromium does not seem to play all Theora files (might be related to
timestamp problems), while VP8 is supported in both Firefox and
Chromium.

Similarly Firefox can not play Matroska containers, while webm is
supported in both Firefox and Chromium.

Signed-off-by: Daniel Calviño Sánchez <danxuliu@gmail.com>
Although the recording itself does not require a user uploading the
resulting file does, so it should be limited only to logged in
moderators.

Signed-off-by: Daniel Calviño Sánchez <danxuliu@gmail.com>
Signed-off-by: Daniel Calviño Sánchez <danxuliu@gmail.com>
Given should be used for preconditions, When for the action being tested
and Then for postconditions.

Signed-off-by: Daniel Calviño Sánchez <danxuliu@gmail.com>
The fake recording server just accepts all backend requests (as long as
the validation is correct) and records them to be able to check them
from the integration tests.

Signed-off-by: Daniel Calviño Sánchez <danxuliu@gmail.com>
Signed-off-by: Daniel Calviño Sánchez <danxuliu@gmail.com>
This just updates the conversation property "callRecording" as soon as
the signaling message is received, rather than having to wait until the
whole conversation data is fetched again.

Signed-off-by: Daniel Calviño Sánchez <danxuliu@gmail.com>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

Successfully merging this pull request may close these issues.

Clarify if recording store should use HPB or SIP
3 participants