0

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.

screenshot of an iOS device implying that an AirPlay streaming session is active

photograph of a television showing that AirPlay is not currently streaming any content

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
...
Will Haley
  • 703
  • 1
  • 9
  • 25

1 Answers1

0

The issue is when the device playing the video tries to play it what it really does in the end is load the master.m3u8 playlist and then play the video. Since your m3u8 is protected the device does not have permission to load it. And the cookies in the main browser are not passed to the tv device so in reality it works as expected: a person you don’t know (the tv) is trying to play the video.

Look for ways to only protect the main playlist with a signature in the url itself and then having a middle ware creating cookies to protect the rest of the segments.

We have that working with AWS cloud front and lambda at edge

Cito
  • 1,659
  • 3
  • 22
  • 49