Similar to other questions I've seen I find that I cannot stream my HTTPS (and password protected via JWT/server-side auth) m3u8
TS streams to AirPlay. The files are being served via my own API/web app using HTML.
My HLS stream play fine on my iPhone (iPhone 8 w/ latest iOS at time of writing), but it's AirPlay that seems to fail. Apple's example m3u8 HTTP video stream files for TS and MP4 work as expected from my phone to AirPlay, but my own m3u8
file does not.
I imagine the answer may be within Apple's HTTP Live Streaming (HLS) specification documentation or their WWDC talk on HLS authoring, but I find the reference materials too opaque to follow as a person who is new to HLS streaming in general.
I've tried explicitly opting in to AirPlay using x-webkit-airplay="allow"
on the video
element as well as switching the server response Content-Type
to application/vnd.apple.mpegurl
from application/x-mpegURL
, but with no success.
I'm using hls.js
to play the videos, and the videos were transcoded like so using ffmpeg
.
ffmpeg -i "${1}" \
-filter_complex "[0:v]split=1[v1]; [v1]scale=w=1080:h=-1[v1out]" \
-map "[v1out]" -c:v:2 libx264 -x264-params "nal-hrd=cbr:force-cfr=1" -b:v:2 5M -maxrate:v:2 5M -minrate:v:2 5M -bufsize:v:2 10M -preset slow -g 48 -sc_threshold 0 -keyint_min 48 \
-map "a:0" -c:a:0 aac -b:a:0 96k -ac 2 \
-f hls \
-hls_time 2 \
-hls_playlist_type vod \
-hls_flags independent_segments \
-hls_segment_type mpegts \
-hls_segment_filename "${2}/${3}/data%02d.ts" \
-var_stream_map "v:0,a:0" "${2}/${3}/stream.m3u8"
My iPhone seemingly shows that the video is currently playing, but AirPlay shows no signs that anything is being played.
Here is a snippet of my m3u8
file...
#EXTM3U
#EXT-X-VERSION:6
#EXT-X-TARGETDURATION:2
#EXT-X-MEDIA-SEQUENCE:0
#EXT-X-PLAYLIST-TYPE:VOD
#EXT-X-INDEPENDENT-SEGMENTS
#EXTINF:2.400000,
data00.ts
#EXTINF:1.600000,
data01.ts
#EXTINF:2.400000,
data02.ts
#EXTINF:1.60
...
...vs Apple's example...
#EXTM3U
#EXT-X-VERSION:6
#EXT-X-INDEPENDENT-SEGMENTS
#EXT-X-STREAM-INF:AVERAGE-BANDWIDTH=2218327,BANDWIDTH=2227464,CODECS="avc1.640020,mp4a.40.2",RESOLUTION=960x540,FRAME-RATE=60.000,CLOSED-CAPTIONS="cc1",AUDIO="aud1",SUBTITLES="sub1"
v5/prog_index.m3u8
#EXT-X-STREAM-INF:AVERAGE-BANDWIDTH=8144656,BANDWIDTH=8178040,CODECS="avc1.64002a,mp4a.40.2",RESOLUTION=1920x1080,FRAME-RATE=60.000,CLOSED-CAPTIONS="cc1",AUDIO="aud1",SUBTITLES="sub1"
v9/prog_index.m3u8
#EXT-X-STREAM-INF:AVERAGE-BANDWIDTH=6307144,BANDWIDTH=6453202,CODECS="avc1.64002a,mp4a.40.2",RESOLUTION=1920x1080,FRAME-RATE=60.000,CLOSED-CAPTIONS="cc1",AUDIO="aud1",SUBTITLES="sub1"
v8/prog_index.m3u8
#EXT-X-STREAM-INF:AVERAGE-BANDWIDTH=4775338,BANDWIDTH=5054232,CODECS="avc1.64002a,mp4a.40.2",RESOLUTION=1920x1080,FRAME-RATE=60.000,CLOSED-CAPTIONS="cc1",AUDIO="aud1",SUBTITLES="sub1"
v7/prog_index.m3u8
#EXT-X-STREAM-INF:AVERAGE-BANDWIDTH=3240596,BANDWIDTH=3289288,CODECS="avc1.640020,mp4a.40.2",RESOLUTION=1280x720,FRAME-RATE=60.000,CLOSED-CAPTIONS="cc1",AUDIO="aud1",SUBTITLES="sub1"
v6/prog_index.m3u8
#EXT-X-STREAM-INF:AVERAGE-BANDWIDTH=1292926,BANDWIDTH=1296989,CODECS="avc1.64001e,mp4a.40.2",RESOLUTION=768x432,FRAME-RATE=30.000,CLOSED-CAPTIONS="cc1",AUDIO="aud1",SUBTITLES="sub1"
v4/prog_index.m3u8
#EXT-X-STREAM-INF:AVERAGE-BANDWIDTH=914722,BANDWIDTH=922242,CODECS="avc1.64001e,mp4a.40.2",RESOLUTION=640x360,FRAME-RATE=30.000,CLOSED-CAPTIONS="cc1",AUDIO="aud1",SUBTITLES="sub1"
v3/prog_index.m3u8
#EXT-X-STREAM-INF:AVERAGE-BANDWIDTH=541239,BANDWIDTH=553010,CODECS="avc1.640015,mp4a.40.2",RESOLUTION=480x270,FRAME-RATE=30.000,CLOSED-CAPTIONS="cc1",AUDIO="aud1",SUBTITLES="sub1"
v2/prog_index.m3u8
#EXT-X-STREAM-INF:AVERAGE-BANDWIDTH=2439704,BANDWIDTH=2448841,CODECS="avc1.640020,ac-3",RESOLUTION=960x540,FRAME-RATE=60.000,CLOSED-CAPTIONS="cc1",AUDIO="aud2",SUBTITLES="sub1"
v5/prog_index.m3u8
#EXT-X-STREAM-INF:AVERAGE-BANDWIDTH=8366033,BANDWIDTH=8399417,CODECS="avc1.64002a,ac-3",RESOLUTION=1920x1080,FRAME-RATE=60.000,CLOSED-CAPTIONS="cc1",AUDIO="aud2",SUBTITLES="sub1"
v9/prog_index.m3u8
...