diff --git a/Dockerfile b/Dockerfile index d220d8c..b1f8d2e 100644 --- a/Dockerfile +++ b/Dockerfile @@ -1,5 +1,7 @@ FROM ubuntu:xenial +LABEL maintainer="omar.trigui.tn@gmail.com" + ADD https://github.com/just-containers/s6-overlay/releases/download/v2.0.0.1/s6-overlay-amd64.tar.gz /tmp/ RUN tar xzf /tmp/s6-overlay-amd64.tar.gz -C / && \ rm /tmp/s6-overlay-amd64.tar.gz @@ -28,7 +30,6 @@ RUN apt-get update && \ xvfb \ pulseaudio - COPY package.json /app/ WORKDIR /app/ @@ -36,7 +37,7 @@ WORKDIR /app/ RUN npm install && \ npm audit fix -COPY . /app/ +COPY . . RUN apt-get purge curl -y && \ apt-get clean -y && \ diff --git a/LICENSE b/LICENSE index bd43fa4..32a2e9e 100644 --- a/LICENSE +++ b/LICENSE @@ -1,6 +1,6 @@ MIT License -Copyright (c) 2020 Omar Trigui +Copyright (c) 2020 Omar Trigui Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal diff --git a/README.md b/README.md index b135477..f589834 100644 --- a/README.md +++ b/README.md @@ -1,7 +1,7 @@ ## Url-to-Video ## Overview -Url-to-Video generator allows you to create a video from html source. +Url-to-Video generator allows you to create a video from html source. This project aims mainly to convert HTML content into video which could be useful in several use cases. ## Features @@ -12,12 +12,12 @@ Url-to-Video generator allows you to create a video from html source. * **Node.jsĀ®** a JavaScript runtime built on Chrome's V8 JavaScript engine. * **Pulseaudio** a sound server that provides a number of features on top of the low-level audio interface ALSA on Linux. -## Comparison with the existing solutions -Most of the existing open source solution render web pages badly and they mainly lack audio support. -This solution rised to mitigate these issues. +## Brief insights about the existing solutions +Nowadays, the existing open source solutions are either based on [casperjs](https://www.casperjs.org/) or [puppeteer](https://github.com/puppeteer/puppeteer). As a result, the generated videos doesn't cover well rendered web pages and they mainly lack audio support. +Fortunately, this project rised to mitigate these issues and fill the gap. ## How to test it - +After executing the following command, you will notice a new file created in the following destination `/tmp/forever_tracey.mp4`. ```bash docker run --rm \ -v /tmp/:/recordings/ \ @@ -26,19 +26,18 @@ docker run --rm \ -e OUTPUT_FILENAME=forever_tracey.mp4 \ cipheredbytes/url-to-video ``` - -You will notice a new file created in the following destination [/tmp/forever_tracey.mp4](https://github.com/OmarTrigui/url-to-video/raw/master/samples/forever_tracey.mp4). +This is a [sample](./samples/forever_tracey.mp4) output file. ## Development -Go to the project directory and run the following command: +Run the following commands to build and run the project: ```bash git https://github.com/OmarTrigui/url-to-video.git && cd url-to-video/ make docker.build docker.run ``` -## TODO list +## Todo list - [ ] Add E2E tests - [ ] Tweak recording performance @@ -47,4 +46,9 @@ make docker.build docker.run ## Contributing Contributions are always welcome, whether adding/suggesting new features, bug fixes, -documenting new file formats or simply editing some grammar. \ No newline at end of file +documenting new file formats or simply editing some grammar. + +## License + +This project is licensed under the MIT license - check the [LICENSE](./LICENSE) file for +details. diff --git a/contributors.md b/contributors.md index 4f208df..4d1ffeb 100644 --- a/contributors.md +++ b/contributors.md @@ -1,4 +1,4 @@ # Contributors to html-to-video -Includes all git commit authors. Aliases are GitHub user names. +Includes all git commit authors. * OmarTrigui \ No newline at end of file diff --git a/entrypoint.sh b/entrypoint.sh index c62cef0..86c9b56 100755 --- a/entrypoint.sh +++ b/entrypoint.sh @@ -1,60 +1,61 @@ #!/bin/bash main() { - log_i "Starting pulseaudio server" - launch_pulseaudio - log_i "Starting xvfb virtual display frame buffer." - launch_xvfb - node main.js + log_i "Starting pulseaudio server" + launch_pulseaudio + log_i "Starting xvfb virtual display frame buffer." + launch_xvfb + log_i "Start recording." + launch_recorder } launch_xvfb() { - local xvfbLockFilePath="/tmp/.X1-lock" - if [ -f "${xvfbLockFilePath}" ] - then - log_i "Removing xvfb lock file '${xvfbLockFilePath}'..." - if ! rm -v "${xvfbLockFilePath}" - then - log_e "Failed to remove xvfb lock file" - exit 1 - fi + local xvfbLockFilePath="/tmp/.X1-lock" + if [ -f "${xvfbLockFilePath}" ]; then + log_i "Removing xvfb lock file '${xvfbLockFilePath}'..." + if ! rm -v "${xvfbLockFilePath}"; then + log_e "Failed to remove xvfb lock file" + exit 1 fi + fi + + export DISPLAY=${XVFB_DISPLAY:-:1} + local screen=${XVFB_SCREEN:-0} + local resolution=${XVFB_RESOLUTION:-1280x720x24} + local timeout=${XVFB_TIMEOUT:-5} + + Xvfb "${DISPLAY}" -screen "${screen}" "${resolution}" & + local loopCount=0 + until xdpyinfo -display "${DISPLAY}" >/dev/null 2>&1; do + loopCount=$((loopCount + 1)) + sleep 1 + if [ "${loopCount}" -gt "${timeout}" ]; then + log_e "xvfb failed to start" + exit 1 + fi + done +} - export DISPLAY=${XVFB_DISPLAY:-:1} - local screen=${XVFB_SCREEN:-0} - local resolution=${XVFB_RESOLUTION:-1280x720x24} - local timeout=${XVFB_TIMEOUT:-5} - - Xvfb "${DISPLAY}" -screen "${screen}" "${resolution}" & - local loopCount=0 - until xdpyinfo -display "${DISPLAY}" > /dev/null 2>&1 - do - loopCount=$((loopCount+1)) - sleep 1 - if [ "${loopCount}" -gt "${timeout}" ] - then - log_e "xvfb failed to start" - exit 1 - fi - done +launch_pulseaudio() { + pulseaudio -D --exit-idle-time=-1 & } -launch_pulseaudio(){ - pulseaudio -D --exit-idle-time=-1 & +launch_recorder() { + node main.js } log_i() { - log "[INFO] ${@}" + log "[INFO] ${@}" } log_e() { - log "[ERROR] ${@}" + log "[ERROR] ${@}" } log() { - echo "[$(date '+%Y-%m-%d %H:%M:%S')] ${@}" + echo "[$(date '+%Y-%m-%d %H:%M:%S')] ${@}" } main -exit \ No newline at end of file +exit diff --git a/main.js b/main.js index 4534dd8..f722029 100644 --- a/main.js +++ b/main.js @@ -25,7 +25,8 @@ function getStartChromeCommand () { '--no-sandbox ' + '--disable-extensions ' + '--autoplay-policy=no-user-gesture-required ' + - '--allow-running-insecure-content --disable-features=TranslateUI"' + '--allow-running-insecure-content ' + + '--disable-features=TranslateUI"' } function getStartRecordingCommand () { @@ -53,7 +54,7 @@ function getStartRecordingCommand () { `/recordings/${process.env.OUTPUT_FILENAME}` } -async function startChrome () { +async function fireChrome () { exec(getStartChromeCommand()) await waitOn(opts) @@ -68,25 +69,25 @@ async function startChrome () { await Network.enable() await Page.enable() - await Page.navigate({ - url: process.env.URL - }) + await Page.navigate({ url: process.env.URL }) await Page.loadEventFired() console.log('All assets are loaded') } async function fireRecorder () { + console.log('Firing recorder') await exec(getStartRecordingCommand()) console.log('Recording completed') } async function init () { try { - await startChrome() + await fireChrome() await fireRecorder() } catch (err) { console.error(err) + process.exit(1) } finally { process.exit() }