Skip to content

Commit

Permalink
Initial set of files to support video recording (#1111) [deploy][prer…
Browse files Browse the repository at this point in the history
…elease]

* Initial set of files to support video recording

* Adding Selenium Grid logo as wallpaper for Fluxbox

* Adding video image build to Makefile

* Fixing copy&paste error

* Adding docker-compose-v3-video.yml as example

* Simple docs showing how to use video container

* Adjusting tags in docker-compose-v3-video.yml

* Updating script that updates tags and dates in docs

* Removing ambiguous commentary

* Adding ffmpeg version to release notes
  • Loading branch information
diemol committed Sep 21, 2020
1 parent 7e48f59 commit 1a3b0e1
Show file tree
Hide file tree
Showing 11 changed files with 259 additions and 2 deletions.
21 changes: 19 additions & 2 deletions Makefile
Expand Up @@ -10,8 +10,20 @@ BUILD_ARGS := $(BUILD_ARGS)
MAJOR := $(word 1,$(subst ., ,$(TAG_VERSION)))
MINOR := $(word 2,$(subst ., ,$(TAG_VERSION)))
MAJOR_MINOR_PATCH := $(word 1,$(subst -, ,$(TAG_VERSION)))
FFMPEG_TAG_VERSION := $(or $(FFMPEG_TAG_VERSION),$(FFMPEG_TAG_VERSION),ffmpeg-4.3.1)

all: hub distributor router sessions event_bus chrome firefox opera standalone_chrome standalone_firefox standalone_opera
all: hub \
distributor \
router \
sessions \
event_bus \
chrome \
firefox \
opera \
standalone_chrome \
standalone_firefox \
standalone_opera \
video

generate_all: \
generate_hub \
Expand Down Expand Up @@ -106,6 +118,9 @@ generate_standalone_opera:
standalone_opera: opera generate_standalone_opera
cd ./StandaloneOpera && docker build $(BUILD_ARGS) -t $(NAME)/standalone-opera:$(TAG_VERSION) .

video:
cd ./Video && docker build $(BUILD_ARGS) -t $(NAME)/video:$(FFMPEG_TAG_VERSION)-$(BUILD_DATE) .


# https://github.com/SeleniumHQ/docker-selenium/issues/992
# Additional tags for browser images
Expand Down Expand Up @@ -257,6 +272,7 @@ release: tag_major_minor
docker push $(NAME)/standalone-chrome:$(MAJOR_MINOR_PATCH)
docker push $(NAME)/standalone-firefox:$(MAJOR_MINOR_PATCH)
docker push $(NAME)/standalone-opera:$(MAJOR_MINOR_PATCH)
docker push $(NAME)/video:$(FFMPEG_TAG_VERSION)-$(BUILD_DATE)

test: test_chrome \
test_firefox \
Expand Down Expand Up @@ -316,4 +332,5 @@ test_opera_standalone:
standalone_firefox \
tag_latest \
tag_and_push_browser_images \
test
test \
video
5 changes: 5 additions & 0 deletions NodeBase/Dockerfile.txt
Expand Up @@ -120,6 +120,11 @@ RUN sudo chmod -R 777 ${HOME} \
COPY start-vnc.sh \
/opt/bin/

#==============================
# Selenium Grid logo as wallpaper for Fluxbox
#==============================
COPY selenium_grid_logo.png /usr/share/images/fluxbox/ubuntu-light.png

#============================
# Some configuration options
#============================
Expand Down
Binary file added NodeBase/selenium_grid_logo.png
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
42 changes: 42 additions & 0 deletions README.md
Expand Up @@ -128,6 +128,48 @@ instructions on top of it.

___

## Video recording ![BETA](https://img.shields.io/badge/beta!-blue?style=for-the-badge)

It is possible to record your tests running in containers by using the `selenium/video:ffmpeg-4.3.1-20200920`
Docker image. One container is needed per each container where a browser is running. This means if you are
running 5 Nodes/Standalone containers, you will need 5 video containers, the mapping is 1-1.

Currently, the only way to do this mapping is manually (either starting the containers manually, or through
`docker-compose`). We are iterating on this process and probably this setup will be more simple in the future.

The video Docker image we provide is based on the ffmpeg Ubuntu image provided by the
[jrottenberg/ffmpeg](https://github.com/jrottenberg/ffmpeg) project, thank you for providing this image and
simplifying our work :tada:

**Notes**:
- If you have questions or feedback, please use the community contact points shown [here](https://www.selenium.dev/support/).
- Please report any bugs through GitHub [issues](https://github.com/SeleniumHQ/docker-selenium/issues/new/choose), and provide
all the information requested on the template.
- Video recording for headless browsers is not supported.
- Video recording tends to use considerable amounts of CPU. Normally you should estimate 1CPU per video container,
and 1 CPU per browser container.
- Videos are stored in the `/videos` directory inside the video container. Map a local directory to get the videos.
- If you are running more than one video container, be sure to overwrite the video file name through the `FILE_NAME`
environment variable to avoid unexpected results.

This example shows how to start the containers manually:

``` bash
$ docker network create grid
$ docker run -d -p 4444:4444 -p 6900:5900 --net grid --name selenium -v /dev/shm:/dev/shm selenium/standalone-chrome:4.0.0-alpha-7-20200907
$ docker run -d --net grid --name video -v /tmp/videos:/videos selenium/video:ffmpeg-4.3.1-20200907
# Run your tests
$ docker stop video && docker rm video
$ docker stop selenium && docker rm selenium
```
After the containers are stopped and removed, you should see a video file on your machine's `/tmp/videos` directory.

Here is an example using a Hub and 3 Nodes (Chrome, Firefox, and Opera):

[`docker-compose-v3-video.yml`](docker-compose-v3-video.yml)

___

## Deploying to Kubernetes (:warning: not tested yet with Selenium 4 images)

Check out [the Kubernetes examples](https://github.com/kubernetes/examples/tree/master/staging/selenium)
Expand Down
32 changes: 32 additions & 0 deletions Video/Dockerfile
@@ -0,0 +1,32 @@
FROM jrottenberg/ffmpeg:4.3.1-ubuntu1804
LABEL authors="Selenium <selenium-developers@googlegroups.com>"

#================================================
# Customize sources for apt-get
#================================================
RUN echo "deb http://archive.ubuntu.com/ubuntu bionic main universe\n" > /etc/apt/sources.list \
&& echo "deb http://archive.ubuntu.com/ubuntu bionic-updates main universe\n" >> /etc/apt/sources.list \
&& echo "deb http://security.ubuntu.com/ubuntu bionic-security main universe\n" >> /etc/apt/sources.list

# No interactive frontend during docker build
ENV DEBIAN_FRONTEND=noninteractive \
DEBCONF_NONINTERACTIVE_SEEN=true

#========================
# Supervisor
#========================
RUN apt-get -qqy update \
&& apt-get -qqy --no-install-recommends install \
supervisor x11-xserver-utils \
&& rm -rf /var/lib/apt/lists/* /var/cache/apt/*

#======================================
# Add Supervisor configuration file
#======================================
COPY supervisord.conf /etc
COPY entry_point.sh video.sh /opt/bin/

RUN mkdir -p /var/run/supervisor /var/log/supervisor /videos

ENTRYPOINT ["/opt/bin/entry_point.sh"]
CMD ["/opt/bin/entry_point.sh"]
15 changes: 15 additions & 0 deletions Video/entry_point.sh
@@ -0,0 +1,15 @@
#!/usr/bin/env bash

/usr/bin/supervisord --configuration /etc/supervisord.conf &

SUPERVISOR_PID=$!

function shutdown {
echo "Trapped SIGTERM/SIGINT/x so shutting down supervisord..."
kill -s SIGTERM ${SUPERVISOR_PID}
wait ${SUPERVISOR_PID}
echo "Shutdown complete"
}

trap shutdown SIGTERM SIGINT
wait ${SUPERVISOR_PID}
27 changes: 27 additions & 0 deletions Video/supervisord.conf
@@ -0,0 +1,27 @@
; Documentation of this file format -> http://supervisord.org/configuration.html

[supervisord]
childlogdir=/var/log/supervisor ; ('AUTO' child log dir, default $TEMP)
logfile=/var/log/supervisor/supervisord.log ; (main log file;default $CWD/supervisord.log)
logfile_maxbytes=50MB ; (max main logfile bytes b4 rotation;default 50MB)
logfile_backups=10 ; (num of main logfile rotation backups;default 10)
loglevel=info ; (log level;default info; others: debug,warn,trace)
pidfile=/var/run/supervisor/supervisord.pid ; (supervisord pidfile;default supervisord.pid)
nodaemon=true ; (start in foreground if true;default false)
minfds=1024 ; (min. avail startup file descriptors;default 1024)
minprocs=200 ; (min. avail process descriptors;default 200)

[program:video-recording]
priority=0
command=/opt/bin/video.sh
autostart=true
autorestart=false
startsecs=0
startretries=0
stopsignal=INT

;Logs (all activity redirected to stdout so it can be seen through "docker logs"
redirect_stderr=true
stdout_logfile=/dev/stdout
stdout_logfile_maxbytes=0

27 changes: 27 additions & 0 deletions Video/video.sh
@@ -0,0 +1,27 @@
#!/bin/sh

VIDEO_SIZE=${VIDEO_SIZE:-"1360x1020"}
DISPLAY_CONTAINER_NAME=${DISPLAY_CONTAINER_NAME:-"selenium"}
DISPLAY=${DISPLAY:-"99"}
FILE_NAME=${FILE_NAME:-"video.mp4"}
FRAME_RATE=${FRAME_RATE:-"15"}
CODEC=${CODEC:-"libx264"}
PRESET=${PRESET:-"-preset ultrafast"}

return_code=1
max_attempts=50
attempts=0
echo 'Checking if the display is open...'
until [ $return_code -eq 0 -o $attempts -eq $max_attempts ]; do
xset -display ${DISPLAY_CONTAINER_NAME}:${DISPLAY} b off > /dev/null 2>&1
return_code=$?
if [ $return_code -ne 0 ]; then
echo 'Waiting before next display check...'
sleep 0.5
fi
attempts=$((attempts+1))
done

# exec replaces the video.sh process with ffmpeg, this makes easier to pass the process termination signal
exec ffmpeg -y -f x11grab -video_size ${VIDEO_SIZE} -r ${FRAME_RATE} -i ${DISPLAY_CONTAINER_NAME}:${DISPLAY}.0 -codec:v ${CODEC} ${PRESET} -pix_fmt yuv420p "/videos/$FILE_NAME"

81 changes: 81 additions & 0 deletions docker-compose-v3-video.yml
@@ -0,0 +1,81 @@
# To execute this docker-compose yml file use `docker-compose -f docker-compose-v3-video.yml up`
# Add the `-d` flag at the end for detached execution
# To stop the execution, hit Ctrl+C, and then `docker-compose -f docker-compose-v3-video.yml down`
version: "3"
services:
chrome:
image: selenium/node-chrome:4.0.0-alpha-7-prerelease-20200907
volumes:
- /dev/shm:/dev/shm
depends_on:
- selenium-hub
environment:
- SE_EVENT_BUS_HOST=selenium-hub
- SE_EVENT_BUS_PUBLISH_PORT=4442
- SE_EVENT_BUS_SUBSCRIBE_PORT=4443
ports:
- "6900:5900"

firefox:
image: selenium/node-firefox:4.0.0-alpha-7-prerelease-20200907
volumes:
- /dev/shm:/dev/shm
depends_on:
- selenium-hub
environment:
- SE_EVENT_BUS_HOST=selenium-hub
- SE_EVENT_BUS_PUBLISH_PORT=4442
- SE_EVENT_BUS_SUBSCRIBE_PORT=4443
ports:
- "6901:5900"

opera:
image: selenium/node-opera:4.0.0-alpha-7-prerelease-20200907
volumes:
- /dev/shm:/dev/shm
depends_on:
- selenium-hub
environment:
- SE_EVENT_BUS_HOST=selenium-hub
- SE_EVENT_BUS_PUBLISH_PORT=4442
- SE_EVENT_BUS_SUBSCRIBE_PORT=4443
ports:
- "6902:5900"

chrome_video:
image: selenium/video:ffmpeg-4.3.1-20200920
volumes:
- /tmp/videos:/videos
depends_on:
- chrome
environment:
- DISPLAY_CONTAINER_NAME=chrome
- FILE_NAME=chrome_video.mp4

firefox_video:
image: selenium/video:ffmpeg-4.3.1-20200920
volumes:
- /tmp/videos:/videos
depends_on:
- firefox
environment:
- DISPLAY_CONTAINER_NAME=firefox
- FILE_NAME=firefox_video.mp4

opera_video:
image: selenium/video:ffmpeg-4.3.1-20200907
volumes:
- /tmp/videos:/videos
depends_on:
- opera
environment:
- DISPLAY_CONTAINER_NAME=firefox
- FILE_NAME=opera_video.mp4

selenium-hub:
image: selenium/hub:4.0.0-alpha-7-prerelease-20200907
container_name: selenium-hub
ports:
- "4442:4442"
- "4443:4443"
- "4444:4444"
2 changes: 2 additions & 0 deletions generate_release_notes.sh
Expand Up @@ -17,6 +17,7 @@ FIREFOX_VERSION=$(docker run --rm selenium/node-firefox:${TAG_VERSION} firefox -
GECKODRIVER_VERSION=$(docker run --rm selenium/node-firefox:${TAG_VERSION} geckodriver --version | awk 'NR==1{print $2}')
OPERA_VERSION=$(docker run --rm selenium/node-opera:${TAG_VERSION} opera --version)
OPERADRIVER_VERSION=$(docker run --rm selenium/node-opera:${TAG_VERSION} operadriver --version | awk 'NR==1{print $2}')
FFMPEG_VERSION=$(docker run --entrypoint="" --rm selenium/video:ffmpeg-4.3.1-${BUILD_DATE} ffmpeg -version | awk '{print $3}' | head -n 1)


echo "" >> release_notes.md
Expand All @@ -28,6 +29,7 @@ echo "* Firefox: ${FIREFOX_VERSION}" >> release_notes.md
echo "* GeckoDriver: ${GECKODRIVER_VERSION}" >> release_notes.md
echo "* Opera: ${OPERA_VERSION}" >> release_notes.md
echo "* OperaDriver: ${OPERADRIVER_VERSION}" >> release_notes.md
echo "* ffmpeg: ${FFMPEG_VERSION}" >> release_notes.md

echo "" >> release_notes.md
echo "### Published Docker images" >> release_notes.md
Expand Down
9 changes: 9 additions & 0 deletions update_tag_in_docs_and_files.sh
Expand Up @@ -2,6 +2,8 @@

LATEST_TAG=$1
NEXT_TAG=$2
LATEST_DATE=$(echo ${LATEST_TAG} | sed 's/.*-//')
NEXT_DATE=$4$(echo ${NEXT_TAG} | sed 's/.*-//')

echo -e "\033[0;32m Updating tag displayed in docs and files...\033[0m"
echo -e "\033[0;32m LATEST_TAG -> ${LATEST_TAG}\033[0m"
Expand All @@ -10,6 +12,13 @@ echo -e "\033[0;32m NEXT_TAG -> ${NEXT_TAG}\033[0m"
# If you want to test this locally and you are using macOS, do `brew install gnu-sed` and change `sed` for `gsed`.
find . \( -type d -name .git -prune \) -o -type f -print0 | xargs -0 sed -i "s/${LATEST_TAG}/${NEXT_TAG}/g"

echo -e "\033[0;32m Updating date used in some docs and files...\033[0m"
echo -e "\033[0;32m LATEST_DATE -> ${LATEST_DATE}\033[0m"
echo -e "\033[0;32m NEXT_DATE -> ${NEXT_DATE}\033[0m"

# If you want to test this locally and you are using macOS, do `brew install gnu-sed` and change `sed` for `gsed`.
find . \( -type d -name .git -prune \) -o -type f -print0 | xargs -0 sed -i "s/${LATEST_DATE}/${NEXT_DATE}/g"

git diff | cat

echo -e "\033[0;32m Text updated...\033[0m"

0 comments on commit 1a3b0e1

Please sign in to comment.