jericho63
Posts: 26
Joined: Mon May 27, 2013 1:20 pm

how stream video into html5 <video>

Fri May 31, 2013 8:58 am

Hello,

I would like to stream the video from csi camera module to html5 page hosted by apache server on raspberry pi.

I have read this blog http://www.recantha.co.uk/blog/?p=4165 but i don't understand how adapt it for html5 video

ps : I'm a noob

Thank you

suzimu
Posts: 6
Joined: Fri May 17, 2013 8:37 pm

Re: how stream video into html5 <video>

Fri May 31, 2013 12:08 pm

as far as i know the html5 video tag just requires a correctly formatted stream. mp4, webm, ogg are the three that appear to be supported. the playback is browser dependent as not all browsers will play all the formats.

here is a good description: http://www.w3schools.com/html/html5_video.asp
it has sample html code, so should work with supported formats.

i have some experience with it in a streaming envoronment using mp4 format files but not with the raspberry pi, yet.

<caveat> i'm a noob too </caveat>

jericho63
Posts: 26
Joined: Mon May 27, 2013 1:20 pm

Re: how stream video into html5 <video>

Sun Jun 02, 2013 6:25 pm

Hello,

thank you for your reply, i will continue to search.

jericho

silentsnake
Posts: 7
Joined: Tue May 21, 2013 7:46 pm

Re: how stream video into html5 <video>

Sun Jun 02, 2013 11:18 pm

What you want to accomplish is called HTTP Live Streaming.

First, you need to get ffmpeg.
Under archlinux run

Code: Select all

pacman -S ffmpeg
and confirm the installation of the required packages.

Second, you need a tool released on GitHub by AndyA. In short, it prepares the output of raspivid for HTTP Live Streaming. If you want more details on that, read README.md.

Code: Select all

pacman -S git
git clone https://github.com/AndyA/psips.git
After obtaining the tool, you need to compile it from source by simply running the following commands:

Code: Select all

cd psips
./configure
make
make install
This could take some minutes on a Raspberry Pi.

Lastly, you need to do some configuration. Therefore edit examples/hls.hs with your preferred text editor, like this:

Code: Select all

vim examples/hls.sh
- Change base=… on line 2 to some directory shared by your http server.
- Change "-c:a libfaac -b:a 128k \" to "-c:a aac -b:a 128k \"
- Change ""live/%08d.ts" < /dev/null" to "-strict 2 "live/%08d.ts" < /dev/null"

Then run the hls.sh script.
Point your webbrowser to the given location and append /live to it. Work flawlessly on Safari and iOS.

This also works if store the output on a shared directory. This is especially important due to the low capacity of the raspberry pi. (In general, you wont to store the files on a server instead of hooking up large usb disks to the Raspberry Pi.)

Downside is that there will be a delay of around 15 - 30 seconds. Depending on your intention this could be more or less critical.

This would also work on Debian, but since Debian used to ship very old versions of their packages you will need to compile the latest version of ffmpeg by hand.

pradeepasakthi
Posts: 1
Joined: Tue Jun 04, 2013 1:21 pm

Re:how to place button on video tag in html5

Tue Jun 04, 2013 1:37 pm

Hi to all,
i need idea how to customized video tag in html5.
(for eg)we need to place video controls on the div tag background with image or place button on the video tag..when we clicked button it will be displayed some image or play another video..am confused..pls help

rbn
Posts: 163
Joined: Tue Dec 27, 2011 8:32 pm
Location: Near Peterborough

Re: how stream video into html5 <video>

Sat Jun 08, 2013 1:36 pm

Hi tried this out, and all seemed to go well, but get this output with error when trying to run.

Code: Select all

pi@raspberrypi ~/psips/examples $ ./hls.sh
+ rm -rf live live.h264 /usr/share/nginx/www/live
+ mkdir -p live
+ ln -s /home/pi/psips/examples/live /usr/share/nginx/www/live
+ mkfifo live.h264
+ sleep 2
+ psips
+ raspivid -w 1280 -h 720 -fps 25 -hf -t 86400000 -b 1800000 -o -
+ ffmpeg -y -i live.h264 -f s16le -i /dev/zero -r:a 48000 -ac 2 -c:v copy -c:a aac -b:a 128k -map 0:0 -map 1:0 -f segment -segment_time 8 -segment_format mpegts -segment_list /usr/share/nginx/www/live.m3u8 -segment_list_size 720 -segment_list_flags live -segment_list_type m3u8 '-strict 2 live/%08d.ts < /dev/null'
ffmpeg version N-53853-g16f3102 Copyright (c) 2000-2013 the FFmpeg developers
  built on Jun  5 2013 17:10:38 with gcc 4.6 (Debian 4.6.3-14+rpi1)
  configuration: 
  libavutil      52. 35.100 / 52. 35.100
  libavcodec     55. 15.100 / 55. 15.100
  libavformat    55.  8.102 / 55.  8.102
  libavdevice    55.  2.100 / 55.  2.100
  libavfilter     3. 75.101 /  3. 75.101
  libswscale      2.  3.100 /  2.  3.100
  libswresample   0. 17.102 /  0. 17.102
Unrecognized option 'strict 2 live/%08d.ts < /dev/null'.
Error splitting the argument list: Option not found
pi@raspberrypi ~/psips/examples $ 
my script is as follows

Code: Select all

pi@raspberrypi ~/psips/examples $ cat hls.sh
#!/bin/bash

base="/usr/share/nginx/www"

set -x

rm -rf live live.h264 "$base/live"
mkdir -p live
ln -s "$PWD/live" "$base/live"

# fifos seem to work more reliably than pipes - and the fact that the
# fifo can be named helps ffmpeg guess the format correctly.
mkfifo live.h264
raspivid -w 1280 -h 720 -fps 25 -hf -t 86400000 -b 1800000 -o - | psips > live.h264 &

# Letting the buffer fill a little seems to help ffmpeg to id the stream
sleep 2

# Need ffmpeg around 1.0.5 or later. The stock Debian ffmpeg won't work.
# I'm not aware of options apart from building it from source. I have
# Raspbian packags built from Debian Multimedia sources. Available on
# request but I don't want to post them publicly because I haven't cross
# compiled all of Debian Multimedia and conflicts can occur.
ffmpeg -y \
  -i live.h264 \
  -f s16le -i /dev/zero -r:a 48000 -ac 2 \
  -c:v copy \
  -c:a aac -b:a 128k \
  -map 0:0 -map 1:0 \
  -f segment \
  -segment_time 8 \
  -segment_format mpegts \
  -segment_list "$base/live.m3u8" \
  -segment_list_size 720 \
  -segment_list_flags live \
  -segment_list_type m3u8 \
 "-strict 2 "live/%08d.ts" < /dev/null" 
using ffmpeg compiled from source, which works OK with other projects to stream the camera output

towolf
Posts: 421
Joined: Fri Jan 18, 2013 2:11 pm

Re: how stream video into html5 <video>

Sat Jun 08, 2013 2:43 pm

Remove the outer pair of quotes on the last line of your script. Why are they there?

rbn
Posts: 163
Joined: Tue Dec 27, 2011 8:32 pm
Location: Near Peterborough

Re: how stream video into html5 <video>

Sat Jun 08, 2013 3:13 pm

Sorted my first problem. Extra quotes in the script last line.
Changed
"-strict 2 "live/%08d.ts" < /dev/null"
to
-strict 2 "live/%08d.ts" < /dev/null

still didn't work..then changed the line to
-strict -2 "live/%08d.ts" < /dev/null"
and restarted as the camera module seemed to have got a bit confused, and it started to produce .ts files as expected.

Now working on the final problems which seems to be permission errors for accessing the live directory via the link
made here in the script, as I'm getting a 403 error from the web-browser
ln -s "$PWD/live" "$base/live"

towolf
Posts: 421
Joined: Fri Jan 18, 2013 2:11 pm

Re: how stream video into html5 <video>

Sat Jun 08, 2013 4:43 pm

To browse a directory in a web browser with the "Index of live" listing you usually need to enable directory listing in your web servers configuration.

rbn
Posts: 163
Joined: Tue Dec 27, 2011 8:32 pm
Location: Near Peterborough

Re: how stream video into html5 <video>

Sat Jun 08, 2013 7:53 pm

I think I have solved the problem.
The issue was with the index.html file in the examples folder. I had copied this to the webserver directory I was using, but then noticed that it refers to the file index.m3u8 (which is also in the examples directory). In fact a populated m3u8 file called live.m3u8 is generated by the script (see the tag -segment_list "$base/live.m3u8" )
Thus I had to modify the index.html file to contain the line
<source src="live.m3u8" type="application/x-mpegURL" /> instead of
<source src="index.m3u8" type="application/x-mpegURL" />

Once I had done this everything worked and it is streaming nicely to my iphone, albeit with a 20 sec or so delay.

Very good picture quality

User avatar
recantha2
Posts: 380
Joined: Wed Nov 14, 2012 9:34 am
Location: Potton, Bedfordshire

Re: how stream video into html5 <video>

Sat Jun 15, 2013 12:48 pm

I think this will only work on Apple browsers/operating systems. Any idea on how to adapt it to work across any OS?
--
Michael Horne - @recantha on Twitter
Raspberry Pi Pod blog - http://www.recantha.co.uk/blog
Cambridge Raspberry Jam - https://camjam.me
Pi Wars - https://piwars.org

jericho63
Posts: 26
Joined: Mon May 27, 2013 1:20 pm

Re: how stream video into html5 <video>

Sun Jun 16, 2013 6:31 pm

Hello,

Thank you for your help and sorry to reply later.

i have try the pips script bu i have this error message : Unknown encoder 'libfaac'

The ffmpeg version on the repository is old, so i have compiled the last version with this option:

Code: Select all

./configure --enable-gpl --enable-libx264  --enable-nonfree --enable-libaacplus
and before i did the same thing for x264 & libaac

Code: Select all

$ cd libaacplus-2.0.2
 ./autogen.sh --enable-shared --enable-static
sudo make
sudo  make install
sudo ldconfig
and

Code: Select all

./configure --enable-static --enable-shared
sudo make
sudo make install
sudo ldconfig
please help me. thank you

jericho

towolf
Posts: 421
Joined: Fri Jan 18, 2013 2:11 pm

Re: how stream video into html5 <video>

Sun Jun 16, 2013 6:56 pm

jericho63 wrote:i have try the pips script bu i have this error message : Unknown encoder 'libfaac'
You compiled with the wrong bad AAC encoder. There’s a range of bad AAC encoders of which faac is the worst. Nowadays the only decent quality AAC audio encoder if fdk-aac, but anyway.

Andy said he encodes empty audio because he thinks some players require audio even if the audio track is empty. I cannot confirm that.

If you want you can delete this

Code: Select all

  -f s16le -i /dev/zero -r:a 48000 -ac 2 \
and this line

Code: Select all

  -c:a libfaac -b:a 128k \
and change this

Code: Select all

-map 0:0 -map 1:0 \
to read

Code: Select all

  -map 0:0 \
That is, remove the useless empty audio track. So no more need for libfaac.

jericho63
Posts: 26
Joined: Mon May 27, 2013 1:20 pm

Re: how stream video into html5 <video>

Mon Jun 17, 2013 4:31 pm

Hello,

Thank you for your help, the script seem work well, i see the files appear in 'live' directory, but the html page don't work, i have this message

"no video with supported format and mime type found"

i execute the script with sudo ./hls.sh otherwise the rights seem not enough

rbn
Posts: 163
Joined: Tue Dec 27, 2011 8:32 pm
Location: Near Peterborough

Re: how stream video into html5 <video>

Mon Jun 17, 2013 5:09 pm

jericho63 wrote:Hello,

Thank you for your help, the script seem work well, i see the files appear in 'live' directory, but the html page don't work, i have this message

"no video with supported format and mime type found"

i execute the script with sudo ./hls.sh otherwise the rights seem not enough
I had a problem with the index file too. I quote what I said in an earlier post
The issue was with the index.html file in the examples folder. I had copied this to the webserver directory I was using, but then noticed that it refers to the file index.m3u8 (which is also in the examples directory). In fact a populated m3u8 file called live.m3u8 is generated by the script (see the tag -segment_list "$base/live.m3u8" )
Thus I had to modify the index.html file to contain the line
<source src="live.m3u8" type="application/x-mpegURL" /> instead of
<source src="index.m3u8" type="application/x-mpegURL" />

jericho63
Posts: 26
Joined: Mon May 27, 2013 1:20 pm

Re: how stream video into html5 <video>

Mon Jun 17, 2013 6:17 pm

Hello,
Yes i have already seen your message and made the same change.

Code: Select all

<html>
  <head>
    <title>PiVid</title>
  </head>
  <body>
    <video controls="controls" width="1280" height="720" autoplay="autoplay" >
      <source src="live.m3u8" type="application/x-mpegURL" />
    </video>
  </body>
</html>
Do you execute the script with sudo also?

towolf
Posts: 421
Joined: Fri Jan 18, 2013 2:11 pm

Re: how stream video into html5 <video>

Mon Jun 17, 2013 6:24 pm

jericho63 wrote: "no video with supported format and mime type found"
Which browser?

jericho63
Posts: 26
Joined: Mon May 27, 2013 1:20 pm

Re: how stream video into html5 <video>

Mon Jun 17, 2013 7:31 pm

with firefox

towolf
Posts: 421
Joined: Fri Jan 18, 2013 2:11 pm

Re: how stream video into html5 <video>

Mon Jun 17, 2013 8:00 pm

Wouldn’t work. It was mentioned further up that this type of HTML5 streaming only works with Apple browsers and some Android versions.

Mozilla and Google refuse to back this standard and back a different standard called MPEG DASH that is even less supported. Next up is MediaSource Javascript API, also not implemented fully.

So for HTML5 live streaming HLS with Apple or Android is your only chance. Otherwise it’s flash plugin and RTMP.

jericho63
Posts: 26
Joined: Mon May 27, 2013 1:20 pm

Re: how stream video into html5 <video>

Tue Jun 18, 2013 6:36 am

Hello,

ok thank you

Jericho

Devfarse
Posts: 9
Joined: Sat Dec 08, 2012 1:44 am

Re: how stream video into html5 <video>

Tue Jul 16, 2013 1:14 am

I am reviving an old thread in order to post an update and see if anyone else has encountered the same issue as me. I have successfully implemented the HLS streaming using information contained here as well as from AndyA's Github. Some changes were needed to the .sh script to get everything functioning but PSIPS/FFMPEG combo works as it should. The one question I had is handling of old .ts segments. The segment list can be of aribitrary length however it appears that additional work needs to go on in the background to clean up the old segments else you will just fill up your SD card. I haven't found any info as to whether this is the appropriate behavior or not however if anyone can shine some light on this it would be very helpful. I was going to start by writing a python script that will parse the .m3u8 list for current segments and delete the old ones in the background.

towolf
Posts: 421
Joined: Fri Jan 18, 2013 2:11 pm

Re: how stream video into html5 <video>

Tue Jul 16, 2013 2:27 am

Code: Select all

‘-segment_wrap limit’
Wrap around segment index once it reaches limit.
That is, it will overwrite and cycle through the old files

docs here: http://ffmpeg.org/ffmpeg-all.html#segme ... c-ssegment

There’s also the simpler -f hls muxer that does pretty much the same thing with less options

docs here: http://ffmpeg.org/ffmpeg-all.html#hls-1

rbn
Posts: 163
Joined: Tue Dec 27, 2011 8:32 pm
Location: Near Peterborough

Re: how stream video into html5 <video>

Tue Jul 16, 2013 7:24 am

The one question I had is handling of old .ts segments. The segment list can be of aribitrary length however it appears that additional work needs to go on in the background to clean up the old segments else you will just fill up your SD card.
Yes this would be a useful addition. I must confess I take the easy way out just now and have an nfs share mounted where I store the segments so space is not currently an issue. I delete them manually from time to time.

Devfarse
Posts: 9
Joined: Sat Dec 08, 2012 1:44 am

Re: how stream video into html5 <video>

Sun Jul 21, 2013 1:25 am

rbn wrote:
The one question I had is handling of old .ts segments. The segment list can be of aribitrary length however it appears that additional work needs to go on in the background to clean up the old segments else you will just fill up your SD card.
Yes this would be a useful addition. I must confess I take the easy way out just now and have an nfs share mounted where I store the segments so space is not currently an issue. I delete them manually from time to time.
Glad someone else asked this question. I have been following this thread for a bit and I ran into this same issue. I solved it by making a quick python script that runs in a separate process to perodically check up on the files and trim out the old ones. I simply parse the m3u8 playlist and remove the old ones. It uses the modules os, sys, time and csv which should all be part of the standard python install.

For operation, it parses the playlist and will look for files in the directory you designate that stores your TS segments. I have it set for the default /usr/share/nginx/www/live. It compares the active files in the playlist with the files in the directory and deletes the ones which aren't referenced in the playlist. I just realized while I was writing this that it may run into a case where if a file is written to the directory before it is added to the playlist then it could be deleted in error. I rearranged the code to change the order and perhaps give it some extra time.

You can call it by simply adding the line

Code: Select all

python m3u8.py &
to the bash script that AndyA wrote. My complete script is below. I would like to improve it in the following ways:
Adding arguments to denote location of files.
Using a variable to set # of segments and wait time in both the sh and python scripts. It currently waits for 60 seconds and then checks every 60 seconds. Operation is pretty lightweight although I am running this all on a headless model A that is only connected via SSH so I don't really see CPU usage during operation.

I compare current and old playlists to see if ffmpeg is still running. If there are no changes then I have it look for all segments and delete them as well as the playlist before it exits. Once ffmpeg exits/breaks it will take up to a minute for the python script to reach this point however it will print to the command line when it does. This isn't helpful for troubleshooting so comment those lines out if you want to keep your old segments on exit.

I use the standard folders for hosting everything on my pi
/usr/share/nginx - hls.sh and m3u8.py are saved here.

Remember to run the script as

Code: Select all

sudo sh hls.sh
as it requires write permissions. Also you should run

Code: Select all

chmod 777 hls.sh
before hand so you have permissions to execute.

/usr/share/nginx/www - index.html is here as well as live.m3u8 which python needs
/usr/share/nginx/www/live - where the ts segments are stored

If your folders are different you will need to change them as necessary in a few different places.

Huge thanks to AndyA for all of his work on this. Rockstar!

Code: Select all

## m3u8.py will parse an m3u8 playlist and remove files which aren't referenced in that playlist.

import os
import sys
import time
import csv

def main():
    print 'm3u8.py running\n'
    time.sleep(60)
    www = '/usr/share/nginx/www'
    live = www + '/live'
    m3u8 ='/usr/share/nginx/www/live.m3u8'
    old_playlist = []
    while True:
	    loc = os.path.abspath(live)
        segments = []
		
        for files in os.listdir(loc):
            if files.endswith('TS') or files.endswith('ts'):
                segments.append(files)

        with open(m3u8,'rb') as rawFile:
            #Read in CSV object
            newData = csv.reader(rawFile)
            dataList = []
            dataList.extend(newData)
            playlist = []
            for rows in dataList:
                data = rows
                if rows[0][-3:] == '.ts':
                    data  = rows[0][5:]
                    #print data
                    #print ' '
                    playlist.append(data)
            # print playlist

        if old_playlist == playlist:
            print 'stream failed'
            if segments:
                for files in segments:
                    segment = live + '/' + files
                    try:
                        os.remove(segment)
                    except OSError:
                        print 'Cannot remove ' + files
                try:
                    os.remove(m3u8)
                except OSError:
                    print 'cannot remove playlist'
            sys.exit()

        for files in segments:
            if not files in playlist:
                segment = live + '/' + files
                try:
                    os.remove(segment)
                except OSError:
                    print 'OSError'

        old_playlist = playlist
        time.sleep(60)

if __name__ == "__main__":
    main()
The script I use to run everything. I also use raspistill to take a picture and drop it in the www folder to add a static image to the video before you select play using the poster tag in the <VIDEO> block.

Code: Select all

#!/bin/bash

base="/usr/share/nginx/www"

set -x

rm -rf live live.h264 "$base/live"
mkdir -p live
ln -s "$PWD/live" "$base/live"

# fifos seem to work more reliably than pipes - and the fact that the
# fifo can be named helps ffmpeg guess the format correctly.
raspistill -w 1280 -h 720 -t 100 -vf -hf -o "$base/poster.jpg"

mkfifo live.h264
raspivid -w 1280 -h 720 -fps 25 -hf -vf -t 86400000 -b 1800000 -o - | psips > live.h264 &

# Letting the buffer fill a little seems to help ffmpeg to id the stream
sleep 2

# Need ffmpeg around 1.0.5 or later.
python m3u8.py &

ffmpeg -y \
  -i live.h264 \
  -f s16le -i /dev/zero -r:a 48000 -ac 2 \
  -c:v copy \
  -c:a aac -b:a 128k \
  -map 0:0 -map 1:0 \
  -f segment \
  -segment_list "$base/live.m3u8" \
  -segment_time 8 \
  -segment_format mpegts \
  -segment_list_size 80 \
  -segment_list_flags live \
  -segment_list_type m3u8 \
  -strict -2 "live/%08d.ts" < /dev/null
Finally my html

Code: Select all

<html>
  <head>
    <title>Raspberry Pi HLS streaming</title>
  </head>
  <body>
    <video controls="controls" width="320" height="180" autoplay="autoplay" poster = poster.jpg >
      <source src="live.m3u8" type="application/x-mpegURL" />
    </video>
  </body>
</html>

towolf
Posts: 421
Joined: Fri Jan 18, 2013 2:11 pm

Re: how stream video into html5 <video>

Sun Jul 21, 2013 10:06 am

You don’t need to delete old segments manually, -segment_wrap takes care of that.

If you set -segment_wrap 10 then it will keep incrementing until 10 and start over at 1.

Return to “Camera board”