mirror of https://github.com/OpenVidu/openvidu.git
Update openvidu-recording image
parent
2b2c2c8d01
commit
a41749602f
|
@ -31,11 +31,12 @@ RUN adduser root pulse-access
|
||||||
# Clean
|
# Clean
|
||||||
RUN apt clean && apt autoclean && apt autoremove
|
RUN apt clean && apt autoclean && apt autoremove
|
||||||
|
|
||||||
COPY entrypoint.sh scripts/composed.sh scripts/composed_quick_start.sh ./
|
COPY entrypoint.sh scripts/composed.sh scripts/composed_quick_start.sh scripts/rtmp.sh ./
|
||||||
COPY utils/xvfb-run-safe /usr/local/bin
|
COPY utils/xvfb-run-safe /usr/local/bin
|
||||||
|
COPY utils/headless-chrome.sh ./
|
||||||
|
|
||||||
# Prepare scripts and folders
|
# Prepare scripts and folders
|
||||||
RUN chmod +x /entrypoint.sh /composed.sh /composed_quick_start.sh \
|
RUN chmod +x /entrypoint.sh /composed.sh /composed_quick_start.sh /rtmp.sh /headless-chrome.sh \
|
||||||
&& chmod +x /usr/local/bin/xvfb-run-safe \
|
&& chmod +x /usr/local/bin/xvfb-run-safe \
|
||||||
&& mkdir /recordings \
|
&& mkdir /recordings \
|
||||||
&& chmod 777 /recordings
|
&& chmod 777 /recordings
|
|
@ -1,9 +1,8 @@
|
||||||
#!/bin/bash -x
|
#!/bin/bash -x
|
||||||
|
|
||||||
# eg: $ ./create_image.sh ubuntu-20-04 86.0.4240.193-1 2.16.0
|
# eg: $ ./create_image.sh 109.0.5414.74-1 2.25.0
|
||||||
OPENVIDU_RECORDING_UBUNTU_VERSION=$1
|
OPENVIDU_RECORDING_CHROME_VERSION=$1 # https://www.ubuntuupdates.org/package_logs?noppa=&page=1&type=ppas&vals=8#
|
||||||
OPENVIDU_RECORDING_CHROME_VERSION=$2 # https://www.ubuntuupdates.org/package_logs?noppa=&page=1&type=ppas&vals=8#
|
OPENVIDU_RECORDING_DOCKER_TAG=$2
|
||||||
OPENVIDU_RECORDING_DOCKER_TAG=$3
|
docker build --rm --pull --no-cache \
|
||||||
docker build --rm --pull --no-cache --build-arg CHROME_VERSION="$OPENVIDU_RECORDING_CHROME_VERSION" \
|
--build-arg CHROME_VERSION="$OPENVIDU_RECORDING_CHROME_VERSION" \
|
||||||
-f $OPENVIDU_RECORDING_UBUNTU_VERSION.Dockerfile \
|
|
||||||
-t openvidu/openvidu-recording:$OPENVIDU_RECORDING_DOCKER_TAG .
|
-t openvidu/openvidu-recording:$OPENVIDU_RECORDING_DOCKER_TAG .
|
|
@ -8,12 +8,14 @@ if [ "$HEADLESS_CHROME_ONLY" == true ]; then
|
||||||
else
|
else
|
||||||
### Use container as OpenVidu recording module ###
|
### Use container as OpenVidu recording module ###
|
||||||
|
|
||||||
RECORDING_TYPE=${RECORDING_TYPE:-COMPOSED}
|
CONTAINER_WORKING_MODE=${CONTAINER_WORKING_MODE:-COMPOSED}
|
||||||
|
|
||||||
if [[ "${RECORDING_TYPE}" == "COMPOSED" ]]; then
|
if [[ "${CONTAINER_WORKING_MODE}" == "COMPOSED" ]]; then
|
||||||
./composed.sh
|
./composed.sh
|
||||||
elif [[ "${RECORDING_TYPE}" == "COMPOSED_QUICK_START" ]]; then
|
elif [[ "${CONTAINER_WORKING_MODE}" == "COMPOSED_QUICK_START" ]]; then
|
||||||
./composed_quick_start.sh
|
./composed_quick_start.sh
|
||||||
|
elif [[ "${CONTAINER_WORKING_MODE}" == "RTMP" ]]; then
|
||||||
|
./rtmp.sh
|
||||||
fi
|
fi
|
||||||
|
|
||||||
fi
|
fi
|
|
@ -3,7 +3,7 @@
|
||||||
# DEBUG MODE
|
# DEBUG MODE
|
||||||
DEBUG_MODE=${DEBUG_MODE:-false}
|
DEBUG_MODE=${DEBUG_MODE:-false}
|
||||||
if [[ ${DEBUG_MODE} == true ]]; then
|
if [[ ${DEBUG_MODE} == true ]]; then
|
||||||
DEBUG_CHROME_FLAGS="--enable-logging --v=1"
|
DEBUG_CHROME_FLAGS="--enable-logging --v=1"
|
||||||
fi
|
fi
|
||||||
|
|
||||||
{
|
{
|
||||||
|
@ -13,8 +13,8 @@ fi
|
||||||
ONLY_VIDEO=${ONLY_VIDEO:-false}
|
ONLY_VIDEO=${ONLY_VIDEO:-false}
|
||||||
RESOLUTION=${RESOLUTION:-1280x720}
|
RESOLUTION=${RESOLUTION:-1280x720}
|
||||||
FRAMERATE=${FRAMERATE:-25}
|
FRAMERATE=${FRAMERATE:-25}
|
||||||
WIDTH="$(cut -d'x' -f1 <<< $RESOLUTION)"
|
WIDTH="$(cut -d'x' -f1 <<<$RESOLUTION)"
|
||||||
HEIGHT="$(cut -d'x' -f2 <<< $RESOLUTION)"
|
HEIGHT="$(cut -d'x' -f2 <<<$RESOLUTION)"
|
||||||
VIDEO_ID=${VIDEO_ID:-video}
|
VIDEO_ID=${VIDEO_ID:-video}
|
||||||
VIDEO_NAME=${VIDEO_NAME:-video}
|
VIDEO_NAME=${VIDEO_NAME:-video}
|
||||||
VIDEO_FORMAT=${VIDEO_FORMAT:-mp4}
|
VIDEO_FORMAT=${VIDEO_FORMAT:-mp4}
|
||||||
|
@ -30,80 +30,37 @@ fi
|
||||||
export VIDEO_NAME
|
export VIDEO_NAME
|
||||||
export VIDEO_FORMAT
|
export VIDEO_FORMAT
|
||||||
export RECORDING_JSON
|
export RECORDING_JSON
|
||||||
|
|
||||||
echo "==== Loaded Environment Variables ======================="
|
echo
|
||||||
|
echo "============= Loaded Environment Variables ============="
|
||||||
env
|
env
|
||||||
echo "========================================================="
|
echo "========================================================"
|
||||||
|
echo
|
||||||
|
|
||||||
### Store Recording json data ###
|
### Store Recording json data ###
|
||||||
|
|
||||||
mkdir /recordings/$VIDEO_ID
|
mkdir -p /recordings/$VIDEO_ID
|
||||||
chmod 777 /recordings/$VIDEO_ID
|
chmod 777 /recordings/$VIDEO_ID
|
||||||
echo $RECORDING_JSON > /recordings/$VIDEO_ID/.recording.$VIDEO_ID
|
echo $RECORDING_JSON >/recordings/$VIDEO_ID/.recording.$VIDEO_ID
|
||||||
|
|
||||||
# Cleanup to be "stateless" on startup, otherwise pulseaudio daemon can't start
|
### Run headless Chrome ###
|
||||||
rm -rf /var/run/pulse /var/lib/pulse /root/.config/pulse
|
|
||||||
# Run pulseaudio
|
|
||||||
pulseaudio -D --system --disallow-exit --disallow-module-loading
|
|
||||||
|
|
||||||
### Start Chrome in headless mode with xvfb, using the display num previously obtained ###
|
source /headless-chrome.sh
|
||||||
|
|
||||||
touch xvfb.log
|
|
||||||
chmod 777 xvfb.log
|
|
||||||
|
|
||||||
xvfb-run-safe --server-args="-ac -screen 0 ${RESOLUTION}x24 -noreset" google-chrome \
|
|
||||||
--kiosk \
|
|
||||||
--start-maximized \
|
|
||||||
--test-type \
|
|
||||||
--no-sandbox \
|
|
||||||
--disable-infobars \
|
|
||||||
--disable-gpu \
|
|
||||||
--disable-popup-blocking \
|
|
||||||
--window-size=$WIDTH,$HEIGHT \
|
|
||||||
--window-position=0,0 \
|
|
||||||
--no-first-run \
|
|
||||||
--disable-features=Translate \
|
|
||||||
--ignore-certificate-errors \
|
|
||||||
--disable-dev-shm-usage \
|
|
||||||
--autoplay-policy=no-user-gesture-required \
|
|
||||||
--simulate-outdated-no-au='Tue, 31 Dec 2099 23:59:59 GMT' \
|
|
||||||
--disable-sync \
|
|
||||||
--no-default-browser-check \
|
|
||||||
--disable-component-update \
|
|
||||||
--disable-background-networking \
|
|
||||||
--disable-default-apps \
|
|
||||||
$DEBUG_CHROME_FLAGS $URL &> xvfb.log &
|
|
||||||
|
|
||||||
touch stop
|
|
||||||
chmod 777 /recordings
|
chmod 777 /recordings
|
||||||
|
|
||||||
until pids=$(pidof Xvfb)
|
|
||||||
do
|
|
||||||
sleep 0.1
|
|
||||||
done
|
|
||||||
|
|
||||||
### Calculate the display num in use parsing args of command "Xvfb"
|
|
||||||
|
|
||||||
XVFB_ARGS=$(ps -eo args | grep [X]vfb)
|
|
||||||
DISPLAY_NUM=$(echo $XVFB_ARGS | sed 's/Xvfb :\([0-9]\+\).*/\1/')
|
|
||||||
echo "Display in use -> :$DISPLAY_NUM"
|
|
||||||
echo "----------------------------------------"
|
|
||||||
|
|
||||||
sleep 2
|
|
||||||
|
|
||||||
### Start recording with ffmpeg ###
|
### Start recording with ffmpeg ###
|
||||||
|
|
||||||
if [[ "$ONLY_VIDEO" == true ]]
|
if [[ "$ONLY_VIDEO" == true ]]; then
|
||||||
then
|
# Do not record audio
|
||||||
# Do not record audio
|
ffmpeg <./stop -y -f x11grab -draw_mouse 0 -framerate $FRAMERATE -video_size $RESOLUTION -i :$DISPLAY_NUM -c:v libx264 -preset ultrafast -crf 28 -refs 4 -qmin 4 -pix_fmt yuv420p -filter:v fps=$FRAMERATE "/recordings/$VIDEO_ID/$VIDEO_NAME.$VIDEO_FORMAT"
|
||||||
<./stop ffmpeg -y -f x11grab -draw_mouse 0 -framerate $FRAMERATE -video_size $RESOLUTION -i :$DISPLAY_NUM -c:v libx264 -preset ultrafast -crf 28 -refs 4 -qmin 4 -pix_fmt yuv420p -filter:v fps=$FRAMERATE "/recordings/$VIDEO_ID/$VIDEO_NAME.$VIDEO_FORMAT"
|
else
|
||||||
else
|
# Record audio ("-f alsa -i pulse [...] -c:a aac")
|
||||||
# Record audio ("-f alsa -i pulse [...] -c:a aac")
|
ffmpeg <./stop -y -f alsa -i pulse -f x11grab -draw_mouse 0 -framerate $FRAMERATE -video_size $RESOLUTION -i :$DISPLAY_NUM -c:a aac -c:v libx264 -preset ultrafast -crf 28 -refs 4 -qmin 4 -pix_fmt yuv420p -filter:v fps=$FRAMERATE "/recordings/$VIDEO_ID/$VIDEO_NAME.$VIDEO_FORMAT"
|
||||||
<./stop ffmpeg -y -f alsa -i pulse -f x11grab -draw_mouse 0 -framerate $FRAMERATE -video_size $RESOLUTION -i :$DISPLAY_NUM -c:a aac -c:v libx264 -preset ultrafast -crf 28 -refs 4 -qmin 4 -pix_fmt yuv420p -filter:v fps=$FRAMERATE "/recordings/$VIDEO_ID/$VIDEO_NAME.$VIDEO_FORMAT"
|
|
||||||
fi
|
fi
|
||||||
|
|
||||||
### Generate video report file ###
|
### Generate video report file ###
|
||||||
ffprobe -v quiet -print_format json -show_format -show_streams /recordings/$VIDEO_ID/$VIDEO_NAME.$VIDEO_FORMAT > /recordings/$VIDEO_ID/$VIDEO_ID.info
|
ffprobe -v quiet -print_format json -show_format -show_streams /recordings/$VIDEO_ID/$VIDEO_NAME.$VIDEO_FORMAT >/recordings/$VIDEO_ID/$VIDEO_ID.info
|
||||||
|
|
||||||
### Update Recording json data ###
|
### Update Recording json data ###
|
||||||
|
|
||||||
|
@ -116,19 +73,18 @@ fi
|
||||||
SIZE=$(echo $INFO | jq '.format.size | tonumber')
|
SIZE=$(echo $INFO | jq '.format.size | tonumber')
|
||||||
DURATION=$(echo $INFO | jq '.format.duration | tonumber')
|
DURATION=$(echo $INFO | jq '.format.duration | tonumber')
|
||||||
|
|
||||||
if [[ "$HAS_AUDIO" == false && "$HAS_VIDEO" == false ]]
|
if [[ "$HAS_AUDIO" == false && "$HAS_VIDEO" == false ]]; then
|
||||||
then
|
STATUS="failed"
|
||||||
STATUS="failed"
|
else
|
||||||
else
|
STATUS="stopped"
|
||||||
STATUS="stopped"
|
|
||||||
fi
|
fi
|
||||||
|
|
||||||
jq -c -r ".hasAudio=$HAS_AUDIO | .hasVideo=$HAS_VIDEO | .duration=$DURATION | .size=$SIZE | .status=\"$STATUS\"" "/recordings/$VIDEO_ID/.recording.$VIDEO_ID" > $TMP && mv $TMP /recordings/$VIDEO_ID/.recording.$VIDEO_ID
|
jq -c -r ".hasAudio=$HAS_AUDIO | .hasVideo=$HAS_VIDEO | .duration=$DURATION | .size=$SIZE | .status=\"$STATUS\"" "/recordings/$VIDEO_ID/.recording.$VIDEO_ID" >$TMP && mv $TMP /recordings/$VIDEO_ID/.recording.$VIDEO_ID
|
||||||
|
|
||||||
### Generate video thumbnail ###
|
### Generate video thumbnail ###
|
||||||
|
|
||||||
MIDDLE_TIME=$(ffmpeg -i /recordings/$VIDEO_ID/$VIDEO_NAME.$VIDEO_FORMAT 2>&1 | grep Duration | awk '{print $2}' | tr -d , | awk -F ':' '{print ($3+$2*60+$1*3600)/2}')
|
MIDDLE_TIME=$(ffmpeg -i /recordings/$VIDEO_ID/$VIDEO_NAME.$VIDEO_FORMAT 2>&1 | grep Duration | awk '{print $2}' | tr -d , | awk -F ':' '{print ($3+$2*60+$1*3600)/2}')
|
||||||
THUMBNAIL_HEIGHT=$((480*$HEIGHT/$WIDTH))
|
THUMBNAIL_HEIGHT=$((480 * $HEIGHT / $WIDTH))
|
||||||
ffmpeg -ss $MIDDLE_TIME -i /recordings/$VIDEO_ID/$VIDEO_NAME.$VIDEO_FORMAT -vframes 1 -s 480x$THUMBNAIL_HEIGHT /recordings/$VIDEO_ID/$VIDEO_ID.jpg
|
ffmpeg -ss $MIDDLE_TIME -i /recordings/$VIDEO_ID/$VIDEO_NAME.$VIDEO_FORMAT -vframes 1 -s 480x$THUMBNAIL_HEIGHT /recordings/$VIDEO_ID/$VIDEO_ID.jpg
|
||||||
|
|
||||||
### Change permissions to all generated files ###
|
### Change permissions to all generated files ###
|
||||||
|
@ -138,9 +94,9 @@ fi
|
||||||
} 2>&1 | tee -a /tmp/container.log
|
} 2>&1 | tee -a /tmp/container.log
|
||||||
|
|
||||||
if [[ ${DEBUG_MODE} == "true" ]]; then
|
if [[ ${DEBUG_MODE} == "true" ]]; then
|
||||||
[[ -f /tmp/container.log ]] && cp /tmp/container.log /recordings/$VIDEO_ID/$VIDEO_ID-container.log || echo "/tmp/container.log not found"
|
[[ -f /tmp/container.log ]] && cp /tmp/container.log /recordings/$VIDEO_ID/$VIDEO_ID-container.log || echo "/tmp/container.log not found"
|
||||||
[[ -f ~/.config/google-chrome/chrome_debug.log ]] && cp ~/.config/google-chrome/chrome_debug.log /recordings/$VIDEO_ID/chrome_debug.log || echo "~/.config/google-chrome/chrome_debug.log"
|
[[ -f ~/.config/google-chrome/chrome_debug.log ]] && cp ~/.config/google-chrome/chrome_debug.log /recordings/$VIDEO_ID/chrome_debug.log || echo "~/.config/google-chrome/chrome_debug.log"
|
||||||
fi
|
fi
|
||||||
|
|
||||||
### Change permissions to all generated files ###
|
### Change permissions to all generated files ###
|
||||||
sudo chmod -R 777 /recordings/$VIDEO_ID
|
sudo chmod -R 777 /recordings/$VIDEO_ID
|
||||||
|
|
|
@ -10,7 +10,7 @@ fi
|
||||||
# Possible values are:
|
# Possible values are:
|
||||||
# - Without parameters: Just execute all necessary configuration for xfvb and start chrome, waiting forever with a session openned
|
# - Without parameters: Just execute all necessary configuration for xfvb and start chrome, waiting forever with a session openned
|
||||||
# - --start-recording: Executes ffmpeg to record a session but don't stop chrome
|
# - --start-recording: Executes ffmpeg to record a session but don't stop chrome
|
||||||
# - --process-recording: Process ffmpeg video and generates a metadata
|
# - --stop-recording: Process ffmpeg video and generates metadata
|
||||||
export COMPOSED_QUICK_START_ACTION=$1
|
export COMPOSED_QUICK_START_ACTION=$1
|
||||||
|
|
||||||
if [[ -z "${COMPOSED_QUICK_START_ACTION}" ]]; then
|
if [[ -z "${COMPOSED_QUICK_START_ACTION}" ]]; then
|
||||||
|
@ -20,58 +20,16 @@ if [[ -z "${COMPOSED_QUICK_START_ACTION}" ]]; then
|
||||||
export RESOLUTION=${RESOLUTION:-1280x720}
|
export RESOLUTION=${RESOLUTION:-1280x720}
|
||||||
export URL=${URL:-https://www.youtube.com/watch?v=JMuzlEQz3uo}
|
export URL=${URL:-https://www.youtube.com/watch?v=JMuzlEQz3uo}
|
||||||
export VIDEO_ID=${VIDEO_ID:-video}
|
export VIDEO_ID=${VIDEO_ID:-video}
|
||||||
export WIDTH="$(cut -d'x' -f1 <<< $RESOLUTION)"
|
export WIDTH="$(cut -d'x' -f1 <<<$RESOLUTION)"
|
||||||
export HEIGHT="$(cut -d'x' -f2 <<< $RESOLUTION)"
|
export HEIGHT="$(cut -d'x' -f2 <<<$RESOLUTION)"
|
||||||
export RECORDING_MODE=${RECORDING_MODE}
|
export RECORDING_MODE=${RECORDING_MODE}
|
||||||
|
|
||||||
# Cleanup to be "stateless" on startup, otherwise pulseaudio daemon can't start
|
### Run headless Chrome ###
|
||||||
rm -rf /var/run/pulse /var/lib/pulse /root/.config/pulse
|
|
||||||
# Run pulseaudio
|
|
||||||
pulseaudio -D --system --disallow-exit --disallow-module-loading
|
|
||||||
|
|
||||||
### Start Chrome in headless mode with xvfb, using the display num previously obtained ###
|
source /headless-chrome.sh
|
||||||
|
|
||||||
touch xvfb.log
|
|
||||||
chmod 777 xvfb.log
|
|
||||||
|
|
||||||
xvfb-run-safe --server-args="-ac -screen 0 ${RESOLUTION}x24 -noreset" google-chrome \
|
|
||||||
--kiosk \
|
|
||||||
--start-maximized \
|
|
||||||
--test-type \
|
|
||||||
--no-sandbox \
|
|
||||||
--disable-infobars \
|
|
||||||
--disable-gpu \
|
|
||||||
--disable-popup-blocking \
|
|
||||||
--window-size=$WIDTH,$HEIGHT \
|
|
||||||
--window-position=0,0 \
|
|
||||||
--no-first-run \
|
|
||||||
--disable-features=Translate \
|
|
||||||
--ignore-certificate-errors \
|
|
||||||
--disable-dev-shm-usage \
|
|
||||||
--autoplay-policy=no-user-gesture-required \
|
|
||||||
--simulate-outdated-no-au='Tue, 31 Dec 2099 23:59:59 GMT' \
|
|
||||||
--disable-sync \
|
|
||||||
--no-default-browser-check \
|
|
||||||
--disable-component-update \
|
|
||||||
--disable-background-networking \
|
|
||||||
--disable-default-apps \
|
|
||||||
$DEBUG_CHROME_FLAGS $URL &> xvfb.log &
|
|
||||||
|
|
||||||
chmod 777 /recordings
|
|
||||||
|
|
||||||
until pids=$(pidof Xvfb)
|
|
||||||
do
|
|
||||||
sleep 0.1
|
|
||||||
done
|
|
||||||
|
|
||||||
### Calculate the display num in use parsing args of command "Xvfb"
|
|
||||||
|
|
||||||
XVFB_ARGS=$(ps -eo args | grep [X]vfb)
|
|
||||||
DISPLAY_NUM=$(echo $XVFB_ARGS | sed 's/Xvfb :\([0-9]\+\).*/\1/')
|
|
||||||
echo "Display in use -> :$DISPLAY_NUM"
|
|
||||||
echo "----------------------------------------"
|
|
||||||
# Save Global Environment variables
|
# Save Global Environment variables
|
||||||
echo "export DISPLAY_NUM=$DISPLAY_NUM" > /tmp/display_num
|
echo "export DISPLAY_NUM=${DISPLAY_NUM}" >/tmp/display_num
|
||||||
|
|
||||||
} 2>&1 | tee -a /tmp/container-start.log
|
} 2>&1 | tee -a /tmp/container-start.log
|
||||||
|
|
||||||
|
@ -89,8 +47,8 @@ elif [[ "${COMPOSED_QUICK_START_ACTION}" == "--start-recording" ]]; then
|
||||||
|
|
||||||
# Variables
|
# Variables
|
||||||
export RESOLUTION=${RESOLUTION:-1280x720}
|
export RESOLUTION=${RESOLUTION:-1280x720}
|
||||||
export WIDTH="$(cut -d'x' -f1 <<< $RESOLUTION)"
|
export WIDTH="$(cut -d'x' -f1 <<<$RESOLUTION)"
|
||||||
export HEIGHT="$(cut -d'x' -f2 <<< $RESOLUTION)"
|
export HEIGHT="$(cut -d'x' -f2 <<<$RESOLUTION)"
|
||||||
export ONLY_VIDEO=${ONLY_VIDEO:-false}
|
export ONLY_VIDEO=${ONLY_VIDEO:-false}
|
||||||
export FRAMERATE=${FRAMERATE:-25}
|
export FRAMERATE=${FRAMERATE:-25}
|
||||||
export VIDEO_ID=${VIDEO_ID:-video}
|
export VIDEO_ID=${VIDEO_ID:-video}
|
||||||
|
@ -98,32 +56,33 @@ elif [[ "${COMPOSED_QUICK_START_ACTION}" == "--start-recording" ]]; then
|
||||||
export VIDEO_FORMAT=${VIDEO_FORMAT:-mp4}
|
export VIDEO_FORMAT=${VIDEO_FORMAT:-mp4}
|
||||||
export RECORDING_JSON="${RECORDING_JSON}"
|
export RECORDING_JSON="${RECORDING_JSON}"
|
||||||
|
|
||||||
echo "==== Loaded Environment Variables - Start Recording ====="
|
echo
|
||||||
|
echo "==== Loaded Environment Variables - Start Recording ===="
|
||||||
env
|
env
|
||||||
echo "========================================================="
|
echo "========================================================"
|
||||||
|
echo
|
||||||
|
|
||||||
### Store Recording json data ###
|
### Store Recording json data ###
|
||||||
|
|
||||||
mkdir /recordings/$VIDEO_ID
|
mkdir -p /recordings/$VIDEO_ID
|
||||||
echo $RECORDING_JSON > /recordings/$VIDEO_ID/.recording.$VIDEO_ID
|
echo $RECORDING_JSON >/recordings/$VIDEO_ID/.recording.$VIDEO_ID
|
||||||
chmod 777 -R /recordings/$VIDEO_ID
|
chmod 777 -R /recordings/$VIDEO_ID
|
||||||
|
|
||||||
# Save Global Environment variables
|
# Save Global Environment variables
|
||||||
env > /tmp/global_environment_vars
|
env >/tmp/global_environment_vars
|
||||||
|
|
||||||
### Start recording with ffmpeg ###
|
### Start recording with ffmpeg ###
|
||||||
|
|
||||||
if [[ "$ONLY_VIDEO" == true ]]
|
if [[ "$ONLY_VIDEO" == true ]]; then
|
||||||
then
|
|
||||||
# Do not record audio
|
# Do not record audio
|
||||||
<./stop ffmpeg -y -f x11grab -draw_mouse 0 -framerate $FRAMERATE -video_size $RESOLUTION -i :$DISPLAY_NUM -c:v libx264 -preset ultrafast -crf 28 -refs 4 -qmin 4 -pix_fmt yuv420p -filter:v fps=$FRAMERATE "/recordings/$VIDEO_ID/$VIDEO_NAME.$VIDEO_FORMAT"
|
ffmpeg <./stop -y -f x11grab -draw_mouse 0 -framerate $FRAMERATE -video_size $RESOLUTION -i :$DISPLAY_NUM -c:v libx264 -preset ultrafast -crf 28 -refs 4 -qmin 4 -pix_fmt yuv420p -filter:v fps=$FRAMERATE "/recordings/$VIDEO_ID/$VIDEO_NAME.$VIDEO_FORMAT"
|
||||||
else
|
else
|
||||||
# Record audio ("-f alsa -i pulse [...] -c:a aac")
|
# Record audio ("-f alsa -i pulse [...] -c:a aac")
|
||||||
<./stop ffmpeg -y -f alsa -i pulse -f x11grab -draw_mouse 0 -framerate $FRAMERATE -video_size $RESOLUTION -i :$DISPLAY_NUM -c:a aac -c:v libx264 -preset ultrafast -crf 28 -refs 4 -qmin 4 -pix_fmt yuv420p -filter:v fps=$FRAMERATE "/recordings/$VIDEO_ID/$VIDEO_NAME.$VIDEO_FORMAT"
|
ffmpeg <./stop -y -f alsa -i pulse -f x11grab -draw_mouse 0 -framerate $FRAMERATE -video_size $RESOLUTION -i :$DISPLAY_NUM -c:a aac -c:v libx264 -preset ultrafast -crf 28 -refs 4 -qmin 4 -pix_fmt yuv420p -filter:v fps=$FRAMERATE "/recordings/$VIDEO_ID/$VIDEO_NAME.$VIDEO_FORMAT"
|
||||||
fi
|
fi
|
||||||
|
|
||||||
# Warn the stop thread about ffmpeg process being completed
|
# Warn the stop thread about ffmpeg process being completed
|
||||||
echo "ffmpeg-completed" > /tmp/$VIDEO_ID-completed.txt
|
echo "ffmpeg-completed" >/tmp/$VIDEO_ID-completed.txt
|
||||||
|
|
||||||
} 2>&1 | tee -a /tmp/container-start-recording.log
|
} 2>&1 | tee -a /tmp/container-start-recording.log
|
||||||
|
|
||||||
|
@ -140,18 +99,17 @@ elif [[ "${COMPOSED_QUICK_START_ACTION}" == "--stop-recording" ]]; then
|
||||||
|
|
||||||
# Stop ffmpeg process
|
# Stop ffmpeg process
|
||||||
FFMPEG_PID=$(pgrep ffmpeg)
|
FFMPEG_PID=$(pgrep ffmpeg)
|
||||||
echo 'q' > stop && tail --pid=$FFMPEG_PID -f /dev/null
|
echo 'q' >stop && tail --pid=$FFMPEG_PID -f /dev/null
|
||||||
|
|
||||||
## Wait for the ffmpeg process to be finished
|
## Wait for the ffmpeg process to be finished
|
||||||
until [ -f /tmp/$VIDEO_ID-completed.txt ]
|
until [ -f /tmp/$VIDEO_ID-completed.txt ]; do
|
||||||
do
|
|
||||||
# Check 20 times per second
|
# Check 20 times per second
|
||||||
sleep 0.05
|
sleep 0.05
|
||||||
done
|
done
|
||||||
rm -f /tmp/$VIDEO_ID-completed.txt
|
rm -f /tmp/$VIDEO_ID-completed.txt
|
||||||
|
|
||||||
### Generate video report file ###
|
### Generate video report file ###
|
||||||
ffprobe -v quiet -print_format json -show_format -show_streams /recordings/$VIDEO_ID/$VIDEO_NAME.$VIDEO_FORMAT > /recordings/$VIDEO_ID/$VIDEO_ID.info
|
ffprobe -v quiet -print_format json -show_format -show_streams /recordings/$VIDEO_ID/$VIDEO_NAME.$VIDEO_FORMAT >/recordings/$VIDEO_ID/$VIDEO_ID.info
|
||||||
|
|
||||||
### Change permissions to all generated files ###
|
### Change permissions to all generated files ###
|
||||||
sudo chmod -R 777 /recordings/$VIDEO_ID
|
sudo chmod -R 777 /recordings/$VIDEO_ID
|
||||||
|
@ -166,14 +124,13 @@ elif [[ "${COMPOSED_QUICK_START_ACTION}" == "--stop-recording" ]]; then
|
||||||
SIZE=$(echo $INFO | jq '.format.size | tonumber')
|
SIZE=$(echo $INFO | jq '.format.size | tonumber')
|
||||||
DURATION=$(echo $INFO | jq '.format.duration | tonumber')
|
DURATION=$(echo $INFO | jq '.format.duration | tonumber')
|
||||||
|
|
||||||
if [[ "$HAS_AUDIO" == false && "$HAS_VIDEO" == false ]]
|
if [[ "$HAS_AUDIO" == false && "$HAS_VIDEO" == false ]]; then
|
||||||
then
|
|
||||||
STATUS="failed"
|
STATUS="failed"
|
||||||
else
|
else
|
||||||
STATUS="stopped"
|
STATUS="stopped"
|
||||||
fi
|
fi
|
||||||
|
|
||||||
jq -c -r ".hasAudio=$HAS_AUDIO | .hasVideo=$HAS_VIDEO | .duration=$DURATION | .size=$SIZE | .status=\"$STATUS\"" "/recordings/$VIDEO_ID/.recording.$VIDEO_ID" > $TMP && mv $TMP /recordings/$VIDEO_ID/.recording.$VIDEO_ID
|
jq -c -r ".hasAudio=$HAS_AUDIO | .hasVideo=$HAS_VIDEO | .duration=$DURATION | .size=$SIZE | .status=\"$STATUS\"" "/recordings/$VIDEO_ID/.recording.$VIDEO_ID" >$TMP && mv $TMP /recordings/$VIDEO_ID/.recording.$VIDEO_ID
|
||||||
rm -f $TMP
|
rm -f $TMP
|
||||||
|
|
||||||
### Change permissions to metadata file ###
|
### Change permissions to metadata file ###
|
||||||
|
@ -182,8 +139,8 @@ elif [[ "${COMPOSED_QUICK_START_ACTION}" == "--stop-recording" ]]; then
|
||||||
### Generate video thumbnail ###
|
### Generate video thumbnail ###
|
||||||
|
|
||||||
MIDDLE_TIME=$(ffmpeg -i /recordings/$VIDEO_ID/$VIDEO_NAME.$VIDEO_FORMAT 2>&1 | grep Duration | awk '{print $2}' | tr -d , | awk -F ':' '{print ($3+$2*60+$1*3600)/2}')
|
MIDDLE_TIME=$(ffmpeg -i /recordings/$VIDEO_ID/$VIDEO_NAME.$VIDEO_FORMAT 2>&1 | grep Duration | awk '{print $2}' | tr -d , | awk -F ':' '{print ($3+$2*60+$1*3600)/2}')
|
||||||
THUMBNAIL_HEIGHT=$((480*$HEIGHT/$WIDTH))
|
THUMBNAIL_HEIGHT=$((480 * $HEIGHT / $WIDTH))
|
||||||
ffmpeg -ss $MIDDLE_TIME -i /recordings/$VIDEO_ID/$VIDEO_NAME.$VIDEO_FORMAT -vframes 1 -s 480x$THUMBNAIL_HEIGHT /recordings/$VIDEO_ID/$VIDEO_ID.jpg &> /tmp/ffmpeg-thumbnail.log
|
ffmpeg -ss $MIDDLE_TIME -i /recordings/$VIDEO_ID/$VIDEO_NAME.$VIDEO_FORMAT -vframes 1 -s 480x$THUMBNAIL_HEIGHT /recordings/$VIDEO_ID/$VIDEO_ID.jpg &>/tmp/ffmpeg-thumbnail.log
|
||||||
|
|
||||||
echo "Recording finished /recordings/$VIDEO_ID/$VIDEO_NAME.$VIDEO_FORMAT"
|
echo "Recording finished /recordings/$VIDEO_ID/$VIDEO_NAME.$VIDEO_FORMAT"
|
||||||
|
|
||||||
|
@ -200,7 +157,3 @@ fi
|
||||||
|
|
||||||
### Change permissions to all generated files ###
|
### Change permissions to all generated files ###
|
||||||
sudo chmod -R 777 /recordings/$VIDEO_ID
|
sudo chmod -R 777 /recordings/$VIDEO_ID
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
|
@ -0,0 +1,47 @@
|
||||||
|
#!/bin/bash
|
||||||
|
|
||||||
|
# DEBUG MODE
|
||||||
|
DEBUG_MODE=${DEBUG_MODE:-false}
|
||||||
|
if [[ ${DEBUG_MODE} == true ]]; then
|
||||||
|
DEBUG_CHROME_FLAGS="--enable-logging --v=1"
|
||||||
|
fi
|
||||||
|
|
||||||
|
{
|
||||||
|
|
||||||
|
### Variables ###
|
||||||
|
|
||||||
|
RTMP_URL=${RTMP_URL}
|
||||||
|
URL=${URL:-https://www.youtube.com/watch?v=JMuzlEQz3uo}
|
||||||
|
RESOLUTION=${RESOLUTION:-1920x1080}
|
||||||
|
FRAMERATE=${FRAMERATE:-25}
|
||||||
|
WIDTH="$(cut -d'x' -f1 <<<$RESOLUTION)"
|
||||||
|
HEIGHT="$(cut -d'x' -f2 <<<$RESOLUTION)"
|
||||||
|
|
||||||
|
export RTMP_URL
|
||||||
|
export URL
|
||||||
|
export RESOLUTION
|
||||||
|
export FRAMERATE
|
||||||
|
export WIDTH
|
||||||
|
export HEIGHT
|
||||||
|
|
||||||
|
echo
|
||||||
|
echo "============= Loaded Environment Variables ============="
|
||||||
|
env
|
||||||
|
echo "========================================================"
|
||||||
|
echo
|
||||||
|
|
||||||
|
### Run headless Chrome ###
|
||||||
|
|
||||||
|
source /headless-chrome.sh
|
||||||
|
|
||||||
|
### Run RTMP command ###
|
||||||
|
|
||||||
|
eval "$RTMP_COMMAND"
|
||||||
|
|
||||||
|
} 2>&1 | tee -a /tmp/container.log
|
||||||
|
|
||||||
|
if [[ ${DEBUG_MODE} == "true" ]]; then
|
||||||
|
mkdir -p /logs
|
||||||
|
[[ -f /tmp/container.log ]] && cp /tmp/container.log /logs/$(date +%s) || echo "/tmp/container.log not found"
|
||||||
|
sudo chmod -R 777 /logs/$(date +%s)
|
||||||
|
fi
|
|
@ -1,40 +0,0 @@
|
||||||
FROM ubuntu:16.04
|
|
||||||
MAINTAINER info@openvidu.io
|
|
||||||
|
|
||||||
ARG CHROME_VERSION
|
|
||||||
|
|
||||||
# Install Chrome
|
|
||||||
RUN apt-get update && apt-get -y upgrade && apt-get install -y wget sudo \
|
|
||||||
# Language Fonts
|
|
||||||
ttf-ancient-fonts fonts-beng fonts-wqy-zenhei fonts-indic
|
|
||||||
|
|
||||||
RUN wget http://dl.google.com/linux/deb/pool/main/g/google-chrome-stable/google-chrome-stable_${CHROME_VERSION}_amd64.deb \
|
|
||||||
&& apt install -y ./google-chrome-stable_${CHROME_VERSION}_amd64.deb \
|
|
||||||
&& rm google-chrome-stable_${CHROME_VERSION}_amd64.deb \
|
|
||||||
&& google-chrome --version
|
|
||||||
|
|
||||||
# Install media packages
|
|
||||||
RUN apt-get install -y software-properties-common
|
|
||||||
RUN add-apt-repository ppa:jonathonf/ffmpeg-4
|
|
||||||
RUN apt-get update
|
|
||||||
RUN apt-get install -y ffmpeg pulseaudio xvfb
|
|
||||||
|
|
||||||
# Install jq for managing JSON
|
|
||||||
RUN apt-get install -y jq
|
|
||||||
|
|
||||||
# Add root user to pulseaudio group
|
|
||||||
RUN adduser root pulse-access
|
|
||||||
|
|
||||||
# Clean
|
|
||||||
RUN apt-get autoclean
|
|
||||||
|
|
||||||
COPY entrypoint.sh scripts/composed.sh scripts/composed_quick_start.sh ./
|
|
||||||
COPY utils/xvfb-run-safe /usr/local/bin
|
|
||||||
|
|
||||||
# Prepare scripts and folders
|
|
||||||
RUN chmod +x /entrypoint.sh /composed.sh /composed_quick_start.sh \
|
|
||||||
&& chmod +x /usr/local/bin/xvfb-run-safe \
|
|
||||||
&& mkdir /recordings \
|
|
||||||
&& chmod 777 /recordings
|
|
||||||
|
|
||||||
ENTRYPOINT /entrypoint.sh
|
|
|
@ -1,43 +0,0 @@
|
||||||
FROM ubuntu:20.04
|
|
||||||
MAINTAINER info@openvidu.io
|
|
||||||
|
|
||||||
ARG CHROME_VERSION
|
|
||||||
|
|
||||||
# Install packages
|
|
||||||
RUN apt-get update && apt-get -y upgrade && apt-get install -y \
|
|
||||||
wget \
|
|
||||||
sudo \
|
|
||||||
gnupg2 \
|
|
||||||
apt-utils \
|
|
||||||
software-properties-common \
|
|
||||||
ffmpeg \
|
|
||||||
pulseaudio \
|
|
||||||
xvfb \
|
|
||||||
jq \
|
|
||||||
# Language Fonts
|
|
||||||
ttf-ancient-fonts fonts-beng fonts-wqy-zenhei fonts-indic \
|
|
||||||
&& rm -rf /var/lib/apt/lists/*
|
|
||||||
|
|
||||||
# Install chrome
|
|
||||||
RUN apt-get update && apt-get -y upgrade && apt-get install -y wget sudo
|
|
||||||
RUN wget http://dl.google.com/linux/deb/pool/main/g/google-chrome-stable/google-chrome-stable_${CHROME_VERSION}_amd64.deb \
|
|
||||||
&& apt install -y ./google-chrome-stable_${CHROME_VERSION}_amd64.deb \
|
|
||||||
&& rm google-chrome-stable_${CHROME_VERSION}_amd64.deb \
|
|
||||||
&& google-chrome --version
|
|
||||||
|
|
||||||
# Add root user to pulseaudio group
|
|
||||||
RUN adduser root pulse-access
|
|
||||||
|
|
||||||
# Clean
|
|
||||||
RUN apt-get clean && apt-get autoclean && apt-get autoremove
|
|
||||||
|
|
||||||
COPY entrypoint.sh scripts/composed.sh scripts/composed_quick_start.sh ./
|
|
||||||
COPY utils/xvfb-run-safe /usr/local/bin
|
|
||||||
|
|
||||||
# Prepare scripts and folders
|
|
||||||
RUN chmod +x /entrypoint.sh /composed.sh /composed_quick_start.sh \
|
|
||||||
&& chmod +x /usr/local/bin/xvfb-run-safe \
|
|
||||||
&& mkdir /recordings \
|
|
||||||
&& chmod 777 /recordings
|
|
||||||
|
|
||||||
ENTRYPOINT /entrypoint.sh
|
|
|
@ -0,0 +1,52 @@
|
||||||
|
#!/bin/bash
|
||||||
|
|
||||||
|
echo
|
||||||
|
echo "================ Running headless Chrome ==============="
|
||||||
|
|
||||||
|
# Cleanup to be "stateless" on startup, otherwise pulseaudio daemon can't start
|
||||||
|
rm -rf /var/run/pulse /var/lib/pulse /root/.config/pulse
|
||||||
|
# Run pulseaudio
|
||||||
|
pulseaudio -D --system --disallow-exit --disallow-module-loading
|
||||||
|
|
||||||
|
### Start Chrome in headless mode with xvfb, using the display num previously obtained ###
|
||||||
|
|
||||||
|
touch xvfb.log
|
||||||
|
chmod 777 xvfb.log
|
||||||
|
|
||||||
|
xvfb-run-safe --server-args="-ac -screen 0 ${RESOLUTION}x24 -noreset" google-chrome \
|
||||||
|
--kiosk \
|
||||||
|
--start-maximized \
|
||||||
|
--test-type \
|
||||||
|
--no-sandbox \
|
||||||
|
--disable-infobars \
|
||||||
|
--disable-gpu \
|
||||||
|
--disable-popup-blocking \
|
||||||
|
--window-size=$WIDTH,$HEIGHT \
|
||||||
|
--window-position=0,0 \
|
||||||
|
--no-first-run \
|
||||||
|
--disable-features=Translate \
|
||||||
|
--ignore-certificate-errors \
|
||||||
|
--disable-dev-shm-usage \
|
||||||
|
--autoplay-policy=no-user-gesture-required \
|
||||||
|
--simulate-outdated-no-au='Tue, 31 Dec 2099 23:59:59 GMT' \
|
||||||
|
--disable-sync \
|
||||||
|
--no-default-browser-check \
|
||||||
|
--disable-component-update \
|
||||||
|
--disable-background-networking \
|
||||||
|
--disable-default-apps \
|
||||||
|
$DEBUG_CHROME_FLAGS $URL &>xvfb.log &
|
||||||
|
|
||||||
|
until pids=$(pidof Xvfb); do
|
||||||
|
sleep 0.1
|
||||||
|
echo "Waiting for Xvfb to start..."
|
||||||
|
done
|
||||||
|
|
||||||
|
touch stop
|
||||||
|
|
||||||
|
### Calculate the display num in use parsing args of command "Xvfb"
|
||||||
|
|
||||||
|
export XVFB_ARGS=$(ps -eo args | grep [X]vfb)
|
||||||
|
export DISPLAY_NUM=$(echo $XVFB_ARGS | sed 's/Xvfb :\([0-9]\+\).*/\1/')
|
||||||
|
echo "Display in use -> :$DISPLAY_NUM"
|
||||||
|
echo "========================================================"
|
||||||
|
echo
|
|
@ -2,21 +2,20 @@
|
||||||
|
|
||||||
# allow settings to be updated via environment
|
# allow settings to be updated via environment
|
||||||
: "${xvfb_lockdir:=/recordings/.xvfb-locks}" # Lock folder necessary to block displays
|
: "${xvfb_lockdir:=/recordings/.xvfb-locks}" # Lock folder necessary to block displays
|
||||||
: "${xvfb_display_min:=99}" # Min display
|
: "${xvfb_display_min:=99}" # Min display
|
||||||
: "${xvfb_display_max:=599}" # Max display
|
: "${xvfb_display_max:=599}" # Max display
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
mkdir -p -- "$xvfb_lockdir" || exit
|
mkdir -p -- "$xvfb_lockdir" || exit
|
||||||
|
|
||||||
i=$xvfb_display_min # minimum display number
|
i=$xvfb_display_min # minimum display number
|
||||||
while (( i < xvfb_display_max )); do
|
while ((i < xvfb_display_max)); do
|
||||||
if [ -f "/tmp/.X$i-lock" ]; then
|
if [ -f "/tmp/.X$i-lock" ]; then
|
||||||
(( ++i )); continue
|
((++i))
|
||||||
|
continue
|
||||||
fi
|
fi
|
||||||
exec 5>"$xvfb_lockdir/$i" || continue
|
exec 5>"$xvfb_lockdir/$i" || continue
|
||||||
if flock -x -n 5; then
|
if flock -x -n 5; then
|
||||||
exec xvfb-run --server-num="$i" "$@" || exit
|
exec xvfb-run --server-num="$i" "$@" || exit
|
||||||
fi
|
fi
|
||||||
(( i++ ))
|
((i++))
|
||||||
done
|
done
|
||||||
|
|
Loading…
Reference in New Issue