Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to share & WebRTC stream from /dev/videoX device from a Chromium on host and Chromium in a docker container

Environment

  • Host running Ubuntu 14.04.5 LTS
  • Docker version 17.09.0-ce, build afdb6d4
  • Chromium 62.0.3202.89
  • 2 webcams: /dev/video0, /dev/video1

Cameras

# v4l2-ctl --list-devices
Venus USB2.0 Camera (usb-0000:00:1a.0-1.2.2):
    /dev/video1

USB 2.0 Camera (usb-0000:00:1a.0-1.3):
    /dev/video0

I need to share the webcams on Ubuntu 14.04 host to the Ubuntu 16.04 docker container and be able to get the video streams (WebRTC getUserMedia) from each camera on each chromium instance respectively running on the host and the container or on 2 separate docker containers.

To test the getUserMedia, I am browsing to

  • https://www.onlinemictest.com/webcam-test/ and
  • https://webrtc.github.io/samples/src/content/getusermedia/gum/

How to reproduce

Dockerfile

FROM ubuntu:16.04

# Install chromium
RUN apt-get update \
    && apt-get install sudo chromium-browser alsa-base alsa-utils alsa-oss -y \
    && rm -rf /var/lib/apt/lists/*

# Create a normal user to run chromium as
RUN useradd --create-home browser \
    && adduser browser video \
    && adduser browser audio \
    && usermod -aG sudo browser
USER browser
WORKDIR /home/browser

ENTRYPOINT ["/usr/bin/chromium-browser", "--use-fake-ui-for-media-stream", "--disable-infobars", "--allow-running-insecure-content", "--ignore-certificate-errors"]
CMD ["https://www.stackoverflow.com/"]

docker-compose up

$ more docker-compose.yml 
version: '3'
services:
  chromium_video1:
    build:
      context: .
      dockerfile: Dockerfile
    image: ubuntu-cr:0.1
#    privileged: true # then you don't need the devices section

    # Pass the URL as an argument (CMD) to ENTRYPOINT in the Dockerfile
    #command: ["https://www.onlinemictest.com/webcam-test/"] # WORKS
    command: ["https://webrtc.github.io/samples/src/content/getusermedia/gum/"] # FAILS

    environment:
        #DISPLAY: $DISPLAY
        DISPLAY:
        XAUTHORITY: /.Xauthority

    devices:
        - /dev/video1
        - /dev/dri
#        - /dev/snd

    volumes:
        - /tmp/.X11-unix:/tmp/.X11-unix
        - ~/.Xauthority:/.Xauthority:ro
        - /var/run/dbus/system_bus_socket:/var/run/dbus/system_bus_socket

    cap_add:
        - SYS_ADMIN

  chromium_video0:
    build:
      context: .
      dockerfile: Dockerfile
    image: ubuntu-cr:0.1
#    privileged: true

    # Pass the URL as an argument (CMD) to ENTRYPOINT in the Dockerfile
    #command: ["https://www.onlinemictest.com/webcam-test/"]
    command: ["https://webrtc.github.io/samples/src/content/getusermedia/gum/"]

    environment:
        DISPLAY:
        XAUTHORITY: /.Xauthority

    devices:
        - /dev/video0
        - /dev/dri
#        - /dev/snd

    volumes:
        - /tmp/.X11-unix:/tmp/.X11-unix
        - ~/.Xauthority:/.Xauthority:ro
        - /var/run/dbus/system_bus_socket:/var/run/dbus/system_bus_socket

    cap_add:
        - SYS_ADMIN

Additional tries with

command: ["https://appear.in/hello"]

and

command: ["https://test.webrtc.org/"]

leads to the same thing, once one cam starts streaming the other can't

Start Chromium in docker containers

export DISPLAY=:0.0 
docker-compose up

RESULTS

Using https://webrtc.github.io/samples/src/content/getusermedia/gum/ => FAILS

https://webrtc.github.io/samples/src/content/getusermedia/gum/ FAILS:(

if I close chromium_video1, then chromium_video0 streams video after a browser refresh (?).

Tried getUserMedia from the web console:

 navigator.mediaDevices.getUserMedia({audio: true, video: true})

GUM Not Readable error

but after closing chromium streaming /dev/video1, now /dev/video0 is readable. The getUserMedia command resolves and the camera streams video from /dev/video0

GUM resolved after closing the streaming Chromium

GUM resolved

They are not accessing the same device. I checked in chrome://media-internals

chrome://media-internals

Using https://www.onlinemictest.com/webcam-test/ WORKS!!!!!?!?!?!

When using https://www.onlinemictest.com/webcam-test/ instead, it works, we can see streams for both cams. I believe that particular site is still using URL.createObjectURL.

https://www.onlinemictest.com/webcam-test/ WORKS?!

images

docker images
REPOSITORY      TAG            IMAGE ID            CREATED             SIZE
ubuntu-cr       0.1            a61f5506b1f9        9 minutes ago       764MB
ubuntu          16.04          747cb2d60bbe        2 months ago        122MB

Open a Chromium browser to the same URL on the host

:( I get the ERROR message

NotReadableError

Any pointers on how to configure my docker container to allow one cam to be assigned to the host while the other is dedicated to the docker container?

Interesting threads

  • NotReadableError: Failed to allocate videosource points that this may be happening because the camera is used by another application.

  • Interestingly, when I open 2 Chromium instances on the host (no container this time) pointing to the same camera test page (getUserMedia), it does manage to get the same video stream to the 2 Chromium instances. That's when I try to access from a container that it conflicts. It can play either one or the other, but not at the same time. So it could be something to configure on the docker container. Still, tring to understand why this is happening.

UPDATE

docker logs

chromium_video1  | libGL error: failed to open drm device: No such file or directory
chromium_video1  | libGL error: failed to load driver: i965
chromium_video0  | libGL error: failed to open drm device: No such file or directory
chromium_video0  | libGL error: failed to load driver: i965

Resolved this one reading this thread

Tried to share devices as suggested in the comments below, to no avail

- /dev/video1:/dev/video1:rm 
- /dev/video1:/dev/video1:r  
- /dev/video1:/dev/video1:rw

Questions

  • What happens when a camera gets accessed and starts streaming? is there a lock file created and where? Note however that I am not accessing the same camera.

On the volumes sections I am sharing

- /tmp/.X11-unix:/tmp/.X11-unix
- ~/.Xauthority:/.Xauthority:ro
- /var/run/dbus/system_bus_socket:/var/run/dbus/system_bus_socket
  • what-is-the-xauthority-file
  • what-is-tmp-x11-unix

I don't think these files are the problem, but still investigating

like image 493
zabumba Avatar asked Dec 18 '17 21:12

zabumba


1 Answers

If you just want separate Chrome sessions you can simply start it with:

chromium-browser --user-data-dir=/tmp/chrome1 

and another instance with

chromium-browser --user-data-dir=/tmp/chrome2

Docker is just a way to document and repeat setting up of a very specific environment. The additional layer of security that it adds in minimal, especially with the extra permissions you're passing on and especially in comparison to Chrome's really well tested security.

If you need a bit more isolation, you can create separate users:

 # run these lines individualy, just press Enter for everything, don't set passwords for them, they won't be able to log in. 
 sudo adduser chrome1
 sudo adduser chrome2 

 # if you want to give each access to only one of the cams you can try this
 sudo chown chrome1:chrome1 /dev/video0 
 sudo chown chrome2:chrome2 /dev/video1
 # keeping in mind unplugging and replugging the camera might reset the permissions unless you update the relevant /etc files

 # to allow anyone to use your X
 xhost +

 # run the two separate browsers
 sudo su - chrome1 -c chromium-browser & 
 sudo su - chrome2 -c chromium-browser &
like image 87
dagelf Avatar answered Oct 15 '22 20:10

dagelf