├── .github
└── workflows
│ └── docker-image.yml
├── Dockerfile
├── LICENSE
├── README.md
├── _config.yml
├── src
├── fluid-player.html
├── htaccess
├── index.html
├── plyr.html
├── videogular.html
└── videojs.html
├── transcode.sh
└── webvtt.sh
/.github/workflows/docker-image.yml:
--------------------------------------------------------------------------------
1 | name: Docker Image CI
2 |
3 | on:
4 | workflow_dispatch:
5 | push:
6 | branches: [ latest, edge, jpg-thumbnails, libressl, vtt-preview-generator, webvtt-mt ]
7 |
8 |
9 | jobs:
10 |
11 | build:
12 |
13 | runs-on: ubuntu-latest
14 |
15 | steps:
16 |
17 | - name: Set up QEMU
18 | uses: docker/setup-qemu-action@v1
19 |
20 | - name: Set up Docker Buildx
21 | uses: docker/setup-buildx-action@v1
22 |
23 | - name: Login to DockerHub
24 | if: github.event_name != 'pull_request'
25 | uses: docker/login-action@v1
26 | with:
27 | username: ${{ secrets.DOCKER_HUB_USERNAME }}
28 | password: ${{ secrets.DOCKER_HUB_TOKEN }}
29 |
30 | - name: Login to GitHub Container Registry
31 | if: github.event_name != 'pull_request'
32 | uses: docker/login-action@v1
33 | with:
34 | registry: ghcr.io
35 | username: ${{ github.repository_owner }}
36 | password: ${{ secrets.GHCR_TOKEN }}
37 |
38 | - name: Build and push
39 | id: docker_build
40 | uses: docker/build-push-action@v2
41 | with:
42 | push: ${{ github.event_name != 'pull_request' }}
43 | tags: |
44 | ${{ secrets.DOCKER_HUB_USERNAME }}/${{ secrets.DOCKER_HUB_REPOSITORY }}:${{ github.ref_name }}
45 | ghcr.io/${{ secrets.DOCKER_HUB_USERNAME }}/${{ secrets.DOCKER_HUB_REPOSITORY }}:${{ github.ref_name }}
46 |
--------------------------------------------------------------------------------
/Dockerfile:
--------------------------------------------------------------------------------
1 | FROM alpine:latest
2 |
3 | COPY ./transcode.sh /bin/transcode.sh
4 | COPY ./webvtt.sh /bin/webvtt.sh
5 |
6 | RUN buildDeps="alsa-lib-dev \
7 | build-base \
8 | brotli-static \
9 | bzip2-static \
10 | coreutils \
11 | expat-dev \
12 | faad2-static \
13 | ffmpeg-dev \
14 | freetype-static \
15 | freetype-dev \
16 | git \
17 | glu-dev \
18 | jack-dev \
19 | jpeg-dev \
20 | lame-dev \
21 | libass-dev \
22 | libjpeg-turbo-dev \
23 | libmad-dev \
24 | libogg-dev \
25 | libpng-dev \
26 | libpng-static \
27 | libpulse \
28 | libtheora-dev \
29 | libvorbis-dev \
30 | libvpx-dev \
31 | libwebp-dev \
32 | libxv-dev \
33 | mesa-dev \
34 | mesa-utils \
35 | musl-dev \
36 | openjpeg-dev \
37 | openssl-dev \
38 | opus-dev \
39 | sdl2-dev \
40 | x264-dev \
41 | x265-dev \
42 | xvidcore-static \
43 | yasm-dev \
44 | zlib-static" && \
45 | apk add --no-cache --update ${buildDeps} bash exiv2 ffmpeg libpng libxslt openssl && \
46 | git clone https://github.com/squidpickles/mpd-to-m3u8.git /app/mpd-to-m3u8 && \
47 | rm -rf !$/.git && \
48 | git clone https://github.com/gpac/gpac.git /tmp/gpac && \
49 | cd /tmp/gpac && ./configure --static-bin && make -j4 && make install && make distclean && cd && rm -rf /tmp/gpac && \
50 | apk del ${buildDeps} && rm -rf /var/cache/apk/* && \
51 | chmod +x /bin/transcode.sh && \
52 | chmod +x /bin/webvtt.sh
53 |
54 | COPY ./src /app/src
55 |
56 | WORKDIR /video
57 | ENTRYPOINT ["/bin/transcode.sh"]
58 | CMD ["*.mkv"]
59 |
--------------------------------------------------------------------------------
/LICENSE:
--------------------------------------------------------------------------------
1 | MIT License
2 |
3 | Copyright (c) 2017 majamee
4 |
5 | Permission is hereby granted, free of charge, to any person obtaining a copy
6 | of this software and associated documentation files (the "Software"), to deal
7 | in the Software without restriction, including without limitation the rights
8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9 | copies of the Software, and to permit persons to whom the Software is
10 | furnished to do so, subject to the following conditions:
11 |
12 | The above copyright notice and this permission notice shall be included in all
13 | copies or substantial portions of the Software.
14 |
15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21 | SOFTWARE.
22 |
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 |
2 |
3 | [](https://github.com/majamee/alpine-dash-hls/actions/workflows/docker-image.yml) |
4 | [](https://hub.docker.com/r/majamee/alpine-dash-hls/?target=_blank) [](https://hub.docker.com/r/majamee/alpine-dash-hls/?target=_blank) | [](https://github.com/majamee/alpine-dash-hls/?target=_blank)
5 |
6 |
7 | # [Alpine Dash HLS](https://majamee.de)
8 | A ready-prepared video transcoding pipeline to create DASH/ HLS compatible video files & playlists.
9 |
10 | Recommended usage via Docker [Docker Desktop](https://www.docker.com/products/docker-desktop/?target=_blank) & [Docker Hub](https://hub.docker.com/r/majamee/alpine-dash-hls/?target=_blank).
11 |
12 | # Simplified usage (run in shell/ terminal/ cmd)
13 | Prerequisite: [Docker](https://www.docker.com/?target=_blank) needs to be installed and running.
14 | ```sh
15 | docker pull majamee/alpine-dash-hls
16 | docker run -v /absolute/path/to/video/:/video majamee/alpine-dash-hls name_of_my_video_file.ext
17 | ```
18 | Please just replace in the command above the absolute path to your video file folder and the full file name of your video file to be converted.
19 | You can also use [tags](https://hub.docker.com/r/majamee/alpine-dash-hls/tags/) like `majamee/alpine-dash-hls:edge` (e.g. uses [alpine](https://hub.docker.com/_/alpine/)'s edge version as base).
20 |
21 | There is also a parameter `--transcode-only` which you can append to the `docker run` command, in order to skip the html and image file output.
22 | Example:
23 | ```sh
24 | docker pull majamee/alpine-dash-hls
25 | docker run -v /absolute/path/to/video/:/video majamee/alpine-dash-hls name_of_my_video_file.ext --transcode-only
26 | ```
27 |
28 | ## Examplary toolchain usage
29 | (Based on work of [squidpickles](https://github.com/squidpickles?target=_blank))
30 |
31 | Just use Kitematic to open the shared folder, place your video file in there, replace `"input.mkv"` in the commands below by your input video file (without `""`) and execute the shell commands subsequent into the Docker container.
32 | ```sh
33 | # 1080p@CRF22
34 | ffmpeg -y -threads 0 -i "input.mkv" -an -c:v libx264 -x264opts 'keyint=24:min-keyint=24:no-scenecut' -profile:v high -level 4.0 -vf "scale=min'(1920,iw)':-4" -crf 22 -movflags faststart -write_tmcd 0 intermed_1080p.mp4
35 | # 720p@CRF22
36 | ffmpeg -y -threads 0 -i "input.mkv" -an -c:v libx264 -x264opts 'keyint=24:min-keyint=24:no-scenecut' -profile:v high -level 4.0 -vf "scale=min'(1280,iw)':-4" -crf 22 -movflags faststart -write_tmcd 0 intermed_720p.mp4
37 | # 480p@CRF22
38 | ffmpeg -y -threads 0 -i "input.mkv" -an -c:v libx264 -x264opts 'keyint=24:min-keyint=24:no-scenecut' -profile:v high -level 4.0 -vf "scale=min'(720,iw)':-4" -crf 22 -movflags faststart -write_tmcd 0 intermed_480p.mp4
39 | # 128k AAC audio only
40 | ffmpeg -y -threads 0 -i "input.mkv" -vn -c:a aac -b:a 128k audio_128k.m4a
41 |
42 | # Create MPEG-DASH files (segments & mpd-playlist)
43 | MP4Box -dash 2000 -rap -frag-rap -url-template -dash-profile onDemand -segment-name 'segment_$RepresentationID$' -out playlist.mpd intermed_1080p.mp4 intermed_720p.mp4 intermed_480p.mp4 audio_128k.m4a
44 |
45 | # Create HLS playlists for each quality level
46 | ffmpeg -y -threads 0 -i intermed_1080p.mp4 -i audio_128k.m4a -map 0:v:0 -map 1:a:0 -shortest -acodec copy -vcodec copy -hls_time 2 -hls_list_size 0 -hls_flags single_file segment_1.m3u8
47 | ffmpeg -y -threads 0 -i intermed_720p.mp4 -i audio_128k.m4a -map 0:v:0 -map 1:a:0 -shortest -acodec copy -vcodec copy -hls_time 2 -hls_list_size 0 -hls_flags single_file segment_2.m3u8
48 | ffmpeg -y -threads 0 -i intermed_480p.mp4 -i audio_128k.m4a -map 0:v:0 -map 1:a:0 -shortest -acodec copy -vcodec copy -hls_time 2 -hls_list_size 0 -hls_flags single_file segment_3.m3u8
49 | ffmpeg -y -threads 0 -i audio_128k.m4a -acodec copy -vcodec copy -hls_time 2 -hls_list_size 0 -hls_flags single_file segment_4.m3u8
50 |
51 | # Transform MPD-Master-Playlist to M3U8-Master-Playlist
52 | xsltproc --stringparam run_id "segment" /app/mpd-to-m3u8/mpd_to_hls.xsl playlist.mpd > playlist.m3u8
53 | ```
54 |
55 | I am glad to receive any improvement ideas about this "any video to DASH/ HLS" pipeline.
56 | Especially if someone has any input on integrating better [Apple's support of fragemented mp4 (fmp4) files](https://gpac.wp.imt.fr/tag/hls-fmp4/) in this pipeline.
57 |
58 | Suggestions welcome. :)
59 |
60 | ## General hints for hosting the files (to test streaming)
61 | * Video and playlist files should be hosted best via HTTPS
62 | * DASH requires the .mpd playlist to be set as `Content-Type: application/dash+xml`
63 | * No specific streaming server is required, but your hosting should have progressive downloading enabled
64 | * If using a different domain name for the video files compared to the page where the player is hosted CORS headers need to be set
65 |
66 | ## Tools to test the generated files for streaming
67 | * HLS (e.g. Safari on Mac OS X): https://videojs.github.io/videojs-contrib-hls/ (use the .m3u8 master-playlist)
68 | * DASH (e.g. Firefox/ Chrome): https://reference.dashif.org/dash.js/ (use the latest released version & the .mpd playlist)
69 |
70 | # Features
71 | * Supported devices: iOS (Chrome/ Firefox/ Safari), Android (Chrome/ Firefox), Mac (Chrome/ Firefox/ Safari), Windows (Chrome/ Firefox/ EDGE)
72 | * Creates DASH (VOD) compatible files (including Safari on Mac)
73 | * Creates HLS files for compatibility with Safari on iOS
74 | * Optimizes video files for web playback (`moov` atom)
75 | * Compresses videos using H.264@CRF22 (for best compatibility)
76 | * Compresses audio using AAC@128k (for DASH as separate track to save data)
77 | * Creates automatically 3 quality levels (Full HD/ HD/ DVD quality)
78 | * Fragments video files in 2 second windows to allow dynamic quality switching based on available bandwidth
79 | * Creates master MPD-Playlist which connects everything (MPEG-DASH)
80 | * Creates master M3U8-Playlist for HLS
81 | * Creates all output files neatly stored in a sub-folder matching the video file name in the folder `output` next to the transcoded video file
82 | * Adds also HTML and `.htaccess` file including code ready for inclusion into the own website for playback next to all other created files
83 | * Generates and sets Poster image (from second 3 of the input video file)
84 | * Generates and includes video preview thumbnails (currently only natively supported by [Fluid Player](https://www.fluidplayer.com/?target=_blank) via [WebVTT](http://www.webvtt.cc/?target=_blank))
85 | * Video preview support thumbnail support added for [Video.js](https://videojs.com/?target=_blank) via [videojs-vtt-thumbnails](https://github.com/chrisboustead/videojs-vtt-thumbnails/)
86 | * Included fallback player (`fluid-player.html`) is based on the great work of the devs at [Fluid Player](https://www.fluidplayer.com/?target=_blank)
87 | * Included second fallback player (`plyr.html`) is based on the great work of the devs at [Plyr](https://plyr.io/?target=_blank)
88 | * Included third fallback player (`videogular.html`) is based on the great work of the devs at [Videogular](http://www.videogular.com/?target=_blank)
89 | * Included player (`index.html`) is based on the great work of the guys at [Video.js](https://videojs.com/?target=_blank)
90 |
91 | # Tip
92 | For creating DASH/ HLS compatible files for multiple videos in a single run, please have a look at:
93 | * [https://majamee.de/auto-dash-hls](https://majamee.de/auto-dash-hls/?target=_blank)
94 |
95 | # Demo
96 | [https://majamee.de/demos](https://majamee.de/demos/?target=_blank)
97 |
--------------------------------------------------------------------------------
/_config.yml:
--------------------------------------------------------------------------------
1 | theme: jekyll-theme-cayman
--------------------------------------------------------------------------------
/src/fluid-player.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 | Auto-DASH-HLS Fluid-Player
13 |
14 |
15 |
16 |
17 |
26 |
27 |
28 |
50 |
51 |
--------------------------------------------------------------------------------
/src/htaccess:
--------------------------------------------------------------------------------
1 | # This adds the MIME Types for the different file types used
2 | AddType application/dash+xml .mpd
3 | AddType application/x-mpegURL .m3u8
4 | AddType video/MP2T .ts
5 | AddType video/mp4 .mp4
6 |
7 | # If the video files are hosted on a different location than the player CORS headers
8 | # need to be set to allow browsers access to the resources
9 | # You might want to replace the * with your players origination host so not every page
10 | # can include your hosted content freely, but * is the best for testing the general setup
11 | # as it invokes the least restrictions
12 |
13 | Header set Access-Control-Allow-Origin *
14 | Header set Access-Control-Allow-Credentials true
15 | Header set Access-Control-Allow-Headers "Origin, X-Requested-With, Content-Type, Accept, Range"
16 | Header set Access-Control-Allow-Methods "GET, POST, OPTIONS, HEAD"
17 |
18 |
19 | # Grant access for files
20 |
21 | # Apache < 2.3
22 |
23 | Order allow,deny
24 | Allow from all
25 | Satisfy All
26 |
27 | # Apache ≥ 2.3
28 |
29 | Require all granted
30 |
31 |
32 |
--------------------------------------------------------------------------------
/src/index.html:
--------------------------------------------------------------------------------
1 | fluid-player.html
--------------------------------------------------------------------------------
/src/plyr.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
14 |
15 |
16 |
17 |
18 |
19 | Auto-DASH-HLS Plyr Player
20 |
21 |
22 |
23 |
24 |
31 |
32 |
33 |
52 |
53 |
54 |
55 |
56 |
--------------------------------------------------------------------------------
/src/videogular.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
14 |
15 |
16 |
17 |
18 | Auto-DASH-HLS Videogular Player
19 |
20 |
21 |
22 |
23 |
24 |