I'm trying to stream a live input to a web page, hosted locally.
I guess it should be pretty easy but I can't get where I'm wrong.
Here's my setup:
- a DSLR camera with decent video capabilities
- a Rpi running an up-to-date Raspbian
On the software side:
- Gphoto2 (works perfectly) to grab the video and pipe it to...
- ffmpeg, with v4l2 to get it as /dev/video0
- Gstreamer to actually stream it (after several unsuccessful attempts with ffserver)
The following command line captures the video. It works:
gphoto2 --stdout --capture-movie | ffmpeg -i - -vcodec rawvideo -pix_fmt yuv420p -threads 0 -f v4l2 /dev/video0
This works quite well enough (with 2sec latency, but I could live with that, especially if I can downgrade the video quality later).
I have a http server running on port 8080 (I have several installed for test purposes: Apache, lighttpd, or even the python3 -m http.server 8080
command), this does not seem to have any influence on my problem.
Now the interesting part.
I tried a method using m3u8 file and multiple small video snips loaded and played sequentially in a js player.
Here's the test1.html
<!DOCTYPE html>
<html>
<head>
<meta charset=utf-8 />
<title>My live video</title>
<link href="https://unpkg.com/video.js/dist/video-js.css" rel="stylesheet">
</head>
<body>
<h1>My live video - simple HLS player</h1>
<video-js id="video_id" class="vjs-default-skin" controls preload="auto" width="640" height="360">
<source src="http://192.168.1.179:8080/playlist.m3u8" type="application/x-mpegURL">
</video-js>
<script src="https://unpkg.com/video.js/dist/video.js"></script>
<script src="https://unpkg.com/@videojs/http-streaming/dist/videojs-http-streaming.js"></script>
<script>
var player = videojs('video_id');
</script>
</body>
</html>
and the gstreamer invocation:
gst-launch-1.0 v4l2src device="/dev/video0" ! queue leaky=1 ! \
videoconvert ! clockoverlay ! \
x264enc tune=zerolatency ! mpegtsmux ! \
hlssink playlist-location /home/pi/test/
playlist-root=http://192.168.1.179:8080 location=/home/pi/test/segment_%05d.ts target-duration=5 max-files=5
This actually "works" but the load and latency becomes unbearable (about 30+ seconds delay).
Now, I thought it would be better to keep things simple, so I tried to simply use a HTTP stream.
So I wrote a test2.html with a <video>
tag pointing to the stream I'll pass on port 9090:
<!DOCTYPE html>
<html>
<head>
<meta http-equiv="content-type" content="text/html; charset=utf-8">
<title>gst-stream</title>
</head>
<body>
<video width=320 height=240 autoplay>
<source src="http://192.168.1.179:9090">
</video>
</body>
</html>
And the Gstreamer invocation (I also tried the `udpsink` option, without success):
gst-launch-1.0 v4l2src device="/dev/video0" ! queue leaky=1 ! \
videoconvert ! videoscale ! video/x-raw,width=320,height=240 \
! clockoverlay shaded-background=true font-desc="Sans 38" \
! theoraenc ! oggmux ! tcpserversink host=127.0.0.1 port=9090
This only brings a blank page (the video embed space is there, just blank). Tried to open it through VLC, but this fails miserably with nothing but a "cannot open media" message.
The page is actually loaded, according to the HTTP server log.
I guess nothing is actually streamed on port 9090, but Gstreamer keeps going like it was doing its job flawlessly...
What am I doing wrong?