A quick backstory, I am building a baby-monitor with a Raspberry Pi and writing a web frontend with Node.JS. I have a handful of old phones that I plan to leave around the house so baby-monitors can be scattered about. So far much of the whole system works, except the HLS video components on iPhones.
The HLS video part works on my desktop with Linux/Chromium and my Android/Chrome phone. I am also able to get the HLS video to work on a MacBook (10.13.3) with Chrome. However, my real problem is that I am unable to get the HLS video to work on any iOS mobile device, specifically iOS versions 10.3.3 and 11.2.5.
I use HLS.js on the client-side to set up the video
HTML element. I understand that iOS on mobile devices do not support Media Source Extensions (MSE), which will explain why HLS.js does not work on my iPhones. However, the "native" HLS support on the mobile devices still do not seem to support the format of the media files.
I am using this picam code (from iizukanao) to create the m3u8 playlist and corresponding .ts files from the Pi's camera. I suspect the m3u8 file does not have the format a mobile iOS client wants. I've manually messed with the m3u8 file and I didn't see much of any positive effect. I run the picam module with:
./picam --hlsdir /run/shm/picam/hls --vflip --autoex --alsadev "hw:1,0" --vfr --avcprofile baseline --avclevel 3.1
Example m3u8 file:
#EXTM3U
#EXT-X-VERSION:3
#EXT-X-TARGETDURATION:1
#EXT-X-MEDIA-SEQUENCE:341
#EXT-X-ALLOW-CACHE:NO
#EXTINF:1.07678,
340.ts
#EXTINF:0.31413,
341.ts
#EXT-X-ENDLIST
I think I have the right codec based on this Apple FAQ and the output from ffprobe:
ffprobe https://RPI/hls/index.m3u8
[https @ 0x9667c0] No trailing CRLF found in HTTP header.
[tls @ 0x966980] The TLS connection was non-properly terminated.
[https @ 0x11a67e0] No trailing CRLF found in HTTP header.
Input #0, hls,applehttp, from 'https://RPI/hls/index.m3u8':
Duration: N/A, start: 301.014111, bitrate: N/A
Program 0
Metadata:
variant_bitrate : 0
Stream #0:0: Video: h264 (Main) ([27][0][0][0] / 0x001B), yuv420p, 1280x720, 15.83 tbr, 90k tbn, 180k tbc
Stream #0:1: Audio: aac (LC) ([15][0][0][0] / 0x000F), 48000 Hz, mono, fltp, 43 kb/s
I serve the actual HLS files with nginx and this site config:
server {
listen 8443 ssl;
ssl_certificate RPI.crt;
ssl_certificate_key RPI.key;
ssl_password_file RPI.pass;
server_name RPI;
location /hls {
add_header 'Accept-Ranges' 'bytes';
add_header 'Access-Control-Allow-Origin' '*' always;
add_header 'Access-Control-Expose-Headers' 'Content-Length';
add_header 'Cache-Control' 'no-cache';
if ($request_method = 'OPTIONS') {
add_header 'Access-Control-Allow-Origin' '*';
add_header 'Access-Control-Max-Age' 1728000;
add_header 'Content-Length' 0;
add_header 'Content-Type' 'text/plain charset=UTF-8';
return 204;
}
types {
application/vnd.apple.mpegurl m3u8;
video/mp2t ts;
}
root /run/shm/picam;
}
}
Does anyone have any ideas about why my iPhones think the video is in an unsupported format?
If helpful, the entirety of my code is on Github here: (don't judge my code just yet, it's still a work-in-progress)
(I've replaced various IP addresses, hostnames, and filenames with "RPI")