Skip to content

mclendon99/fmp4streamer

Repository files navigation

fmp4streamer

What is fmp4streamer | How does it work | Capabilities | Installation | Running | Viewing | Configuration | Roadmap | Motivation | Changelog

What is fmp4streamer

The fmp4streamer is a Python application designed to stream hardware encoded H.264 from a V4L2 Linux video device directly to a browser.

How does it work

This python script setups the V4L2 device, reads the h264 stream from it, adds some fMP4 (fragmented MP4) header and serves it via HTTP or HTTPS. It works with only one html5 video tag, no js needed. It's pretty lightweight.

Capabilities

  • Stream to multiple clients simultaneously (usually only limited by your network connection)
  • Support any resolution and framerate the video device can capture
  • Works in any Raspberry Pi with a camera module
  • Able to handle high framerate (60-90 fps) streams
  • Able to stream to iPhone and Safari via HLS.
  • Very low cpu utilization, even when streaming using SSL

Installation

wget https://github.com/soyersoyer/fmp4streamer/archive/refs/tags/v3.0.3.zip
unzip v3.0.3.zip
mv fmp4streamer-3.0.3 fmp4streamer

Installation as a system service

git clone http://www.github.com/mclendon99/fmp4streamer.git
  • Set up the config file

    cd fmp4streamer
    cp fmp4streamer.conf.dist fmp4streamer.conf
    
  • Edit the fmp4streamer.conf file to point to your certificate/key if using HTTPS. (See below).

  • Make any other changes as needed, e.g. port number or frame-rate...

  • Install the config file

    sudo mkdir /etc/fmp4streamer
    sudo cp fmp4streamer.conf /etc/fmp4streamer
    sudo cp fmp4streamer.py /etc/fmp4streamer
    sudo cp bmff.py /etc/fmp4streamer
    sudo cp v4l2camera.py /etc/fmp4streamer
    sudo cp v4l2.py /etc/fmp4streamer
    
  • Install the system service

    sudo cp fmp4streamer.system-service /lib/systemd/system/fmp4streamer.service
    sudo chmod 0644 /lib/systemd/system/fmp4streamer.service
    

    To use https, one must obtain a certificate from a registered domain. GoDaddy has cheap domains and LetsEncrypt will issue a certificate manually after installation of snap and letsencrypt, e.g. the following will manually issue a certificate:

    certbot certonly --authenticator dns-godaddy --dns-godaddy-propogation-seconds 600 --keep-until-expiring  --expand --server https://acme-v02.api.letencrypt.org/directory -d '.your-registered.domain' -d '*.your-registered.domain'
    

    and then put the challenge in the domain record per the instructions and your keys will appear in /etc/letsencrypt/live/your-registered.domain/

    Point to the fullchain.pem certificate and the privkey.pem in the fmp4streamer.conf file.

Running

  • from the terminal

    cd fmp4streamer
    python3 fmp4streamer.py
    
  • At startup. Now installed as a system service.

    cd fmp4streamer
    mkdir -p ~/.config/systemd/user
    cp fmp4streamer.service ~/.config/systemd/user/
    systemctl --user enable fmp4streamer
    systemctl --user start fmp4streamer
    loginctl enable-linger pi
    

    watch the logs

    systemctl --user status fmp4streamer
    journalctl --user-unit fmp4streamer
    

Running as a system service (one time only)

```
sudo systemctl daemon-reload
sudo systemctl enable fmp4streamer.service
sudo systemctl start fmp4streamer.service
```

Watch the logs
```
dmesg
systemctl status fmp4streamer
journalctl --system-unit fmp4streamer
```

Viewing

When fmp4streamer.py is running the stream can be viewed from any browser via the following url. ip_address is the ip address or hostname of your computer, and port (default: 8000) is the port you set in the configuration section.

http://<ip_address>:<port>/

If you want to view the stream via your favourite media player, you can use the

http://<ip_address>:<port>/stream.mp4

url.

Configuration

You can start with the fmp4streamer.conf.dist:

cp fmp4streamer.conf.dist fmp4streamer.conf

Which contains:

[server]
listen = 
port = 8000

[/dev/video0]
width = 800
height = 600
fps = 30
# you can set any V4L2 control too, list them with the -l option
h264_profile = High
h264_level = 4.2
h264_i_frame_period = 15

You can set all the V4L2 controls via the configuration file. List them with

python3 fmp4streamer.py -l

Roadmap

  • Use V4L2 instead of raspivid
  • Adding AAC audio to the stream from ALSA
  • Support multiple cameras
  • Rewrite to c or Rust

Motivation

I wanted to stream my raspberry camera to the browser. I found some solution, but I think they are not optimal or too heavy.

MJPEG streamers

We have h264, why do we want to stream mjpeg?

VLC, Gstreamer, FFmpeg

apt install vlc
...
0 upgraded, 294 newly installed, 0 to remove and 0 not upgraded.
Need to get 107 MB of archives.
After this operation, 900 MB of additional disk space will be used.
apt install libgstreamer-plugins-base1.0 gstreamer1.0-tools
...
0 upgraded, 119 newly installed, 0 to remove and 0 not upgraded.
Need to get 51.5 MB of archives.
After this operation, 633 MB of additional disk space will be used.
apt install ffmpeg
...
0 upgraded, 149 newly installed, 0 to remove and 0 not upgraded.
Need to get 69.3 MB of archives.
After this operation, 714 MB of additional disk space will be used.

These are huge. It's bad because lot of binary contains a lot of security bugs and you have to update these packages too in your project lifetime, not just install them in one time.

You have to add a custom apt repository to your pi to install, you have to trust these guys. It has closed source components too. So no way.

It uses a baseline javascript h264 decoder. We have better h264 decoders in our hardwares, so why do we want to use a javascript decoder?

I like it, it's good, but I don't like its dependencies

apt install python3-picamera
Reading package lists... Done
Building dependency tree       
Reading state information... Done
The following additional packages will be installed:
  libblas3 libgfortran5 liblapack3 python3-numpy
Suggested packages:
  gfortran python-numpy-doc python3-dev python3-pytest python3-numpy-dbg python-picamera-docs
The following NEW packages will be installed:
  libblas3 libgfortran5 liblapack3 python3-numpy python3-picamera
0 upgraded, 5 newly installed, 0 to remove and 0 not upgraded.
Need to get 3,830 kB of archives.
After this operation, 18.1 MB of additional disk space will be used.

Do we really need fortran to use a camera in python? Do we look like dinosaurs? NO! And 18.1 MB for some init and some read?

Fortran dinousaurs

apt install python3-tornado
...
0 upgraded, 1 newly installed, 0 to remove and 0 not upgraded.
Need to get 354 kB of archives.
After this operation, 1,800 kB of additional disk space will be used.

It's for the websocket server, not too big but do we really need websockets? No, simple http is enough for streaming to browsers.

samirkumardas/jmuxer

Why do we want to add mp4 headers to h264 with js in the browser? If we want to do it properly we have to send timing information next to h264 too, but what should be the format, custom encoding or protobuf? Or wait, there is already a format for that, I remember it, the mp4! So it should be done on the server side.

Media Source Extensions

It could be good, but safari on iOS doesn't support it... and why do we need javascript code to play a video?

It inspired me, I like it very much, it's simple and minimal, but it uses websockets and the Media Source Extensions...

fmp4streamer (formerly RaspiWebCam)

So here we are.

It doesn't have any dependencies other than python and V4L2, but they are installed by default.

It adds fMP4 (fragmented MP4) headers to the h264 stream. It uses the python http server to serve it to the browser.

The browsers play it with only one html5 video tag (the most of). No javascript needed.

Safari on iOS plays it only with HLS playlists, but it works too. And the playlists added to the index.html of course.

About

No description, website, or topics provided.

Resources

License

Stars

Watchers

Forks

Packages

No packages published

Contributors 4

  •  
  •  
  •  
  •  

Languages