Encoding HLS video for JW Player 6

The newest JW Player supports reading HLS segmented content in a Flash player (which is very cool). However it didn’t work for me using HLS content created with Apple Compressor or FFmpeg + mediafilesegmenter. What did work was generating transport streams with FFmpeg and the m3u8-segmenter from https://github.com/johnf/m3u8-segmenter.

Generated multiple different bitrates using ffmpeg: (these are the Apple recommended HLS profiles) It’s possible to use named pipes to send the transport streams directly to m3u8-segmenter.

mkdir bbb.mpegts
ffmpeg -y -i bbb.mp4 -threads 0 -f mpegts \
  -acodec libfaac -ab 64k -ar 44100 -vcodec libx264 -vprofile baseline \
    -x264opts "fps=12:keyint=36:bitrate=200"  -s 416x234  bbb.mpegts/p1.ts \
  -acodec libfaac -ab 64k -ar 44100 -vcodec libx264 -vprofile baseline \
    -x264opts "fps=12:keyint=36:bitrate=400"  -s 480x270  bbb.mpegts/p2.ts \
  -acodec libfaac -ab 64k -ar 44100 -vcodec libx264 -vprofile baseline \
    -x264opts "fps=24:keyint=72:bitrate=600"  -s 640x360  bbb.mpegts/p3.ts \
  -acodec libfaac -ab 64k -ar 44100 -vcodec libx264 -vprofile baseline \
    -x264opts "fps=24:keyint=72:bitrate=1200" -s 640x360  bbb.mpegts/p4.ts \
  -acodec libfaac -ab 64k -ar 44100 -vcodec libx264 -vprofile main     \
    -x264opts "fps=24:keyint=72:bitrate=1800" -s 960x540  bbb.mpegts/p5.ts \
  -acodec libfaac -ab 64k -ar 44100 -vcodec libx264 -vprofile main     \
    -x264opts "fps=24:keyint=72:bitrate=2500" -s 960x540  bbb.mpegts/p6.ts \
  -acodec libfaac -ab 64k -ar 44100 -vcodec libx264 -vprofile main     \
    -x264opts "fps=24:keyint=72:bitrate=4500" -s 1280x720 bbb.mpegts/p7.ts

Created segments at six-second intervals, to fit the keyframes generated by ffmpeg:

mkdir bbb.hls
for p in p1 p2 p3 p4 p5 p6 p7; do mkdir bbb.hls/$p.seg; (cd bbb.hls; m3u8-segmenter --input ../bbb.mpegts/$p.ts --duration 6 --output-prefix $p.seg/$p --m3u8-file $p.m3u8 --url-prefix ""); done

Wrote a variant playlist that links all the profiles in ‘bbb.hls’:

#EXTM3U
#EXT-X-STREAM-INF:PROGRAM-ID=1,BANDWIDTH=264000,RESOLUTION=416x234
p1.m3u8
#EXT-X-STREAM-INF:PROGRAM-ID=1,BANDWIDTH=464000,RESOLUTION=480x270
p2.m3u8
#EXT-X-STREAM-INF:PROGRAM-ID=1,BANDWIDTH=664000,RESOLUTION=640x360
p3.m3u8
#EXT-X-STREAM-INF:PROGRAM-ID=1,BANDWIDTH=1264000,RESOLUTION=640x360
p4.m3u8
#EXT-X-STREAM-INF:PROGRAM-ID=1,BANDWIDTH=1864000,RESOLUTION=960x540
p5.m3u8
#EXT-X-STREAM-INF:PROGRAM-ID=1,BANDWIDTH=2564000,RESOLUTION=960x540
p6.m3u8
#EXT-X-STREAM-INF:PROGRAM-ID=1,BANDWIDTH=4564000,RESOLUTION=1280x720
p7.m3u8

The mpegts files can then be deleted, and the on-disk layout should look like this: (probably with many more TS files)

./p1.m3u8
./p1.seg
./p1.seg/p1-1.ts
./p1.seg/p1-2.ts
./p1.seg/p1-3.ts
./p2.m3u8
./p2.seg
./p2.seg/p2-1.ts
./p2.seg/p2-2.ts
./p2.seg/p2-3.ts
./p3.m3u8
./p3.seg
./p3.seg/p3-1.ts
./p3.seg/p3-2.ts
./p3.seg/p3-3.ts
./p4.m3u8
./p4.seg
./p4.seg/p4-1.ts
./p4.seg/p4-2.ts
./p4.seg/p4-3.ts
./p5.m3u8
./p5.seg
./p5.seg/p5-1.ts
./p5.seg/p5-2.ts
./p5.seg/p5-3.ts
./p6.m3u8
./p6.seg
./p6.seg/p6-1.ts
./p6.seg/p6-2.ts
./p6.seg/p6-3.ts
./p7.m3u8
./p7.seg
./p7.seg/p7-1.ts
./p7.seg/p7-2.ts
./p7.seg/p7-3.ts
./playlist.m3u8

If all these files are exposed via an HTTP server, you can pass playlist.m3u8 as the source to JW Player and it should work.

Comments

  • Great post. Thanks!

  • Leave a comment