Skip to content

Docker: FFmpeg with audio devices support (Pulse, Alsa) #2586

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

Merged
merged 1 commit into from
Jan 15, 2025
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: 6 additions & 2 deletions .ffmpeg/Dockerfile
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@ USER root
# Install build tools
#======================================
ARG TOOLS_DEPS="autoconf automake cmake libfreetype6 gcc build-essential libtool make nasm pkg-config zlib1g-dev numactl \
libnuma-dev libx11-dev libxcb-shm0 libxcb1-dev yasm git curl jq wget ca-certificates"
libnuma-dev libx11-dev libxcb-shm0 libxcb1-dev libpulse-dev libasound2-dev yasm git curl jq wget ca-certificates"

RUN apt-get update -qqy \
&& apt-get upgrade -yq \
Expand Down Expand Up @@ -66,6 +66,8 @@ RUN cd /usr/local/src \
--enable-nonfree \
--enable-libx264 \
--enable-libxcb \
--enable-libpulse \
--enable-alsa \
--enable-static \
&& make \
&& make install
Expand All @@ -80,7 +82,9 @@ COPY --from=builder /usr/local/bin/rclone /usr/local/bin/rclone

RUN apt-get -qqy update \
&& apt-get -qqy --no-install-recommends install \
libx11-dev libxcb-shm0 libxcb1-dev \
libx11-dev libxcb-shm0 libxcb1-dev libpulse-dev libasound2-dev \
&& apt-get -qqy update \
&& apt-get -yq upgrade \
&& rm -rf /var/lib/apt/lists/* /var/cache/apt/*

RUN ldd /usr/local/bin/ffmpeg \
Expand Down
6 changes: 4 additions & 2 deletions ENV_VARIABLES.md
Original file line number Diff line number Diff line change
Expand Up @@ -53,7 +53,7 @@
| SE_HTTPS_PRIVATE_KEY | /opt/selenium/secrets/tls.key | | |
| SE_ENABLE_TRACING | true | | |
| SE_OTEL_EXPORTER_ENDPOINT | | | |
| SE_OTEL_SERVICE_NAME | selenium-router | | |
| SE_OTEL_SERVICE_NAME | selenium-standalone-docker | | |
| SE_OTEL_JVM_ARGS | | | |
| SE_OTEL_TRACES_EXPORTER | otlp | | |
| SE_OTEL_JAVA_GLOBAL_AUTOCONFIGURE_ENABLED | true | | |
Expand Down Expand Up @@ -88,7 +88,7 @@
| SE_REJECT_UNSUPPORTED_CAPS | false | | |
| SE_NEW_SESSION_THREAD_POOL_SIZE | | | |
| SE_SESSION_REQUEST_TIMEOUT | 300 | | |
| SE_SESSION_RETRY_INTERVAL | 5 | | |
| SE_SESSION_RETRY_INTERVAL | 15 | | |
| SE_HEALTHCHECK_INTERVAL | 120 | | |
| SE_RELAX_CHECKS | true | | |
| SE_SESSION_QUEUE_HOST | | | |
Expand Down Expand Up @@ -119,3 +119,5 @@
| SE_SUPERVISORD_LOG_FILE | /tmp/supervisord.log | | |
| SE_SUPERVISORD_AUTO_RESTART | true | | |
| SE_SUPERVISORD_START_RETRIES | 5 | | |
| SE_RECORD_AUDIO | false | Flag to enable recording the audio source (default is Pulse Audio input) | |
| SE_AUDIO_SOURCE | -f pulse -ac 2 -i default | FFmpeg arguments to record the audio source | |
2 changes: 1 addition & 1 deletion Router/Dockerfile
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,7 @@ USER ${SEL_UID}
# In seconds, maps to "--session-request-timeout"
ENV SE_SESSION_REQUEST_TIMEOUT="300" \
# In seconds, maps to "--session-retry-interval"
SE_SESSION_RETRY_INTERVAL="5" \
SE_SESSION_RETRY_INTERVAL="15" \
SE_OTEL_SERVICE_NAME="selenium-router"

EXPOSE 4444
Expand Down
6 changes: 5 additions & 1 deletion Video/Dockerfile
Original file line number Diff line number Diff line change
Expand Up @@ -17,9 +17,11 @@ COPY --from=source /usr/local/bin/rclone /usr/local/bin/rclone

RUN apt-get -qqy update \
&& apt-get -qqy --no-install-recommends install \
libx11-dev libxcb-shm0 libxcb1-dev \
libx11-dev libxcb-shm0 libxcb1-dev libpulse-dev libasound2-dev \
x11-xserver-utils x11-utils \
python3-pip \
&& apt-get -qqy update \
&& apt-get -yq upgrade \
&& pip install --upgrade --break-system-packages --no-cache-dir setuptools psutil \
&& rm -rf /var/lib/apt/lists/* /var/cache/apt/*

Expand All @@ -35,6 +37,8 @@ RUN ffmpeg -version \
ENV DISPLAY_NUM="99" \
DISPLAY_CONTAINER_NAME="selenium" \
SE_RECORD_VIDEO="true" \
SE_RECORD_AUDIO="false" \
SE_AUDIO_SOURCE="-f pulse -ac 2 -i default" \
SE_SERVER_PROTOCOL="http" \
SE_VIDEO_POLL_INTERVAL="1" \
SE_SCREEN_WIDTH="1920" \
Expand Down
20 changes: 16 additions & 4 deletions Video/video.sh
Original file line number Diff line number Diff line change
Expand Up @@ -204,14 +204,23 @@ function graceful_exit_force() {
exit 0
}

if [ "${SE_RECORD_AUDIO,,}" = "true" ]; then
echo "$(date -u +"${ts_format}") [${process_name}] - Audio source arguments: ${SE_AUDIO_SOURCE}"
else
SE_AUDIO_SOURCE=""
fi

if [[ "${VIDEO_UPLOAD_ENABLED}" != "true" ]] && [[ "${VIDEO_FILE_NAME}" != "auto" ]] && [[ -n "${VIDEO_FILE_NAME}" ]]; then
trap graceful_exit SIGTERM SIGINT EXIT
wait_for_display
video_file="$VIDEO_FOLDER/$VIDEO_FILE_NAME"
# exec replaces the video.sh process with ffmpeg, this makes easier to pass the process termination signal
ffmpeg -hide_banner -loglevel warning -flags low_delay -threads 2 -fflags nobuffer+genpts -strict experimental -y -f x11grab \
-video_size ${VIDEO_SIZE} -r ${FRAME_RATE} -i ${DISPLAY} -codec:v ${CODEC} ${PRESET} -pix_fmt yuv420p "$video_file" &
wait $!
-video_size ${VIDEO_SIZE} -r ${FRAME_RATE} -i ${DISPLAY} ${SE_AUDIO_SOURCE} -codec:v ${CODEC} ${PRESET} -pix_fmt yuv420p "$video_file" &
FFMPEG_PID=$!
if ps -p $FFMPEG_PID >/dev/null; then
wait $FFMPEG_PID
fi
wait_for_file_integrity

else
Expand Down Expand Up @@ -243,8 +252,11 @@ else
video_file="${VIDEO_FOLDER}/$video_file_name"
echo "$(date -u +"${ts_format}") [${process_name}] - Starting to record video"
ffmpeg -hide_banner -loglevel warning -flags low_delay -threads 2 -fflags nobuffer+genpts -strict experimental -y -f x11grab \
-video_size ${VIDEO_SIZE} -r ${FRAME_RATE} -i ${DISPLAY} -codec:v ${CODEC} ${PRESET} -pix_fmt yuv420p "$video_file" &
recording_started="true"
-video_size ${VIDEO_SIZE} -r ${FRAME_RATE} -i ${DISPLAY} ${SE_AUDIO_SOURCE} -codec:v ${CODEC} ${PRESET} -pix_fmt yuv420p "$video_file" &
FFMPEG_PID=$!
if ps -p $FFMPEG_PID >/dev/null; then
recording_started="true"
fi
echo "$(date -u +"${ts_format}") [${process_name}] - Video recording started"
sleep ${poll_interval}
elif [[ "$session_id" != "$prev_session_id" && "$recording_started" = "true" ]]; then
Expand Down
6 changes: 6 additions & 0 deletions scripts/generate_list_env_vars/description.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -360,3 +360,9 @@
- name: SE_SUPERVISORD_START_RETRIES
description: ''
cli: ''
- name: SE_RECORD_AUDIO
description: Flag to enable recording the audio source (default is Pulse Audio input)
cli: ''
- name: SE_AUDIO_SOURCE
description: FFmpeg arguments to record the audio source
cli: ''
3 changes: 3 additions & 0 deletions scripts/generate_list_env_vars/extract_env.py
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@
def extract_variables_from_shell_scripts(directory_path):
variables = OrderedDict()
for root, _, files in os.walk(directory_path):
files.sort()
for file in files:
if file.endswith(".sh"):
file_path = os.path.join(root, file)
Expand All @@ -23,6 +24,7 @@ def extract_variables_from_shell_scripts(directory_path):
def extract_variables_from_dockerfiles(directory_path):
variables = OrderedDict()
for root, _, files in os.walk(directory_path):
files.sort()
for file in files:
if file.startswith("Dockerfile"):
file_path = os.path.join(root, file)
Expand All @@ -40,6 +42,7 @@ def extract_variables_from_dockerfiles(directory_path):
def combine_dictionaries(dict1, dict2):
combined_dict = OrderedDict(dict1)
combined_dict.update(dict2)
combined_dict = dict(sorted(combined_dict.items()))
return combined_dict

def read_description_yaml(file_path):
Expand Down
Loading
Loading