Live stream your webcam to your iPhone over the Internet, using Nvidia Jetson
In this post, we are creating a password protected web page, which, when assessed using safari on IOS it displays live video, captured from a webcam attached to our Jetson.
Add a web server and make your Jetson accessible over the Internet
For this, we will leverage the amazing Cloudflare Tunnel service. Cloudflare Tunnel is a free service but you need a domain name managed by Cloudflare. You can add a domain by following this guide. Instructions how to set up a tunnel can be found here. In a nutshell the following steps are required.
- Download the .deb package of clouflared for ARM 64 from the Downloads page and install it using apt.
- Run
cloudflared tunnel login
in your terminal and visit the URL that will appear. Select your domain name and press “Authorize”. - Create a new tunnel by executing
cloudflared tunnel create <NAME>
. Note the generated tunnel ID. - Create a configuration file named config.yml inside ~/.cloudflared and put the following content:
url: http://localhost:80
tunnel: <tunnel ID>
credentials-file: /<path to home>/.cloudflared/<tunnel ID>.json
- Map your tunnel to a hostname of your domain (e.g., my-iot.example.com) by executing
cloudflared tunnel route dns <tunnel ID> <hostname>
- Run the tunnel by executing
cloudflared tunnel run <tunnel ID>
Later on, you can see the created tunnels by executing cloudflared tunnel list
.
Create a password-protected site
Create a folder inside /var/www where the generated playlist and the recorded video files will be stored. In the rest of this post, it is assumed that this folder is named stream. Make yourself the owner of newly created folder (using sudo chown
).
Then, create a username and a password that will be used for accessing the protected site. Supposedly, the selected username is “jetson” (it can be anything) execute sudo htpasswd -c /etc/apache2/.htpasswd jetson
We will now create the appropriate apache2 configuration file for hosting our site. Create a .conf file in /etc/apache2/sites-available/ (e.g., jetson.conf) and put the following configuration.
<VirtualHost *:80>
ServerAdmin webmaster@localhost
ServerName <YOUR DOMAIN>
DocumentRoot /var/www/stream
ErrorLog ${APACHE_LOG_DIR}/jetson_error.log
CustomLog ${APACHE_LOG_DIR}/jetson_access.log combined
<Directory "/var/www/stream">
AuthType Basic
AuthName "Protected Content"
AuthUserFile /etc/apache2/.htpasswd
Require valid-user
</Directory>
</VirtualHost>
In order to activate the new site create a link to the create .conf file in /etc/apache2/sites-enabled (e.g., go the directory and execute sudo ln -s ../sites-available/jetson.conf .
and restart apache (sudo service apache2 restart
)
Install FFmpeg
The FFmpeg package included in Ubuntu 18.04 is quite old and in many cases it is incompatibly with many online guidelines. Thankfully, FFmpeg can be easily installed from source, using this guideline. A minimal configuration, suitable for our system is the followings:
./configure \
--pkg-config-flags="--static" \
--extra-libs="-lpthread -lm" \
--ld="g++" \
--enable-gpl \
--enable-nonfree \
--enable-libfdk-aac \
--enable-libx264 \
--enable-libpulse
Detect webcam
In order to detect the internal name used for our webcam we utile the v4l-utils, which is simply installed by executing sudo apt-get install v4l-utils
, then the webcam can be listed by executing v4l2-ctl --list-devices
. The following is a sample output.
UVC Camera (046d:0825) (usb-70090000.xusb-2.2):
/dev/video0
Create HLS stream
After we have executed all these steps, it is time to create the HLS stream. The stream is created by invoking :
ffmpeg -f v4l2 -framerate 25 -video_size 640x480 -i /dev/video0 \
-f alsa -i default -acodec aac \
-hls_time 2 -hls_list_size 5 \
-hls_delete_threshold 2 -hls_flags delete_segments \
/var/www/html/stream/playlist.m3u8
Create an HTML page
Now it is time to create an HTML page that will be used for accessing your video stream. Fortunately, Safari browser on IOS does not need any JavaScript library for accessing HLS streams: a simple HTML5 video tag is enough. The following code will work.
<html lang="en">
<head>
<meta charset=utf-8/>
</head>
<body>
<div id='player'>
<video width="640" height="480" controls>
<source src="playlist.m3u8" type="application/x-mpegURL">
</video>
</div>
</body>
</html>
Place the HTML page inside “/var/www/stream”, start your Cloudflare tunnel, and visit it!