I'm writing a web application for managing and viewing streams from ONVIF ip-cameras.
It's written in nodejs. The idea is to run a child process in node and pipe output to node, then send the buffer to client and render it on canvas. I have a working solution for sending data to client and rendering it on canvas using websockets but it only works on one of my cameras.
I own 2 IP cameras and both of them have rtsp server.
One of them(let's name it camX) kind of works with this ffmpeg command (sometimes it just stops, maybe due to packet losses):
ffmpeg -rtsp_transport tcp -re -i <rtsp_link> -f mjpeg pipe:1
But the other one(camY) returns Nonmatching transport in server reply
and exits.
I discovered that the camY transport is unicast
but ffmpeg doesn't support this particular lower_transport as I read on ffmpeg forum.
So I started looking for a solution. My first idea was to use openRTSP
which works fine with both streams.
I looked at the documentation and came up with this command:
openRTSP -4 -c <rtsp_link> | ffmpeg -re -i pipe:0 -f mjpeg pipe:1
-4
parameter returns stream to pipe in mp4 format
And here's another problem I ran into, ffmpeg returns:
[mov,mp4,m4a,3gp,3g2,mj2 @ 0x559a4b6ba900] moov atom not found
pipe:0: Invalid data found when processing input
Is there any way to make this work? I tried various solutions I found, but none of them worked.
EDIT
As @Gyan suggested I used -i
parameter instead of -4
but it didn't solve my problem.
My command:
openRTSP -V -i -c -K <rtsp_link> | ffmpeg -loglevel debug -re -i pipe:0 -f mjpeg pipe:1
Created receiver for "video/H264" subsession (client ports 49072-49073)
Setup "video/H264" subsession (client ports 49072-49073)
AVIFileSink::setWord(): SeekFile64 failed (err 29)
AVIFileSink::setWord(): SeekFile64 failed (err 29)
AVIFileSink::setWord(): SeekFile64 failed (err 29)
AVIFileSink::setWord(): SeekFile64 failed (err 29)
AVIFileSink::setWord(): SeekFile64 failed (err 29)
AVIFileSink::setWord(): SeekFile64 failed (err 29)
AVIFileSink::setWord(): SeekFile64 failed (err 29)
AVIFileSink::setWord(): SeekFile64 failed (err 29)
AVIFileSink::setWord(): SeekFile64 failed (err 29)
Outputting to the file: "stdout"
[avi @ 0x5612944268c0] Format avi probed with size=2048 and score=100
[avi @ 0x56129442f7a0] use odml:1
Started playing session
Receiving streamed data (signal with "kill -HUP 15028" or "kill -USR1 15028" to terminate)...
^C
[AVIOContext @ 0x56129442f640] Statistics: 16904 bytes read, 0 seeks
pipe:0: Invalid data found when processing input
As you can see openRTSP command return err 29 but in meantime it outputs some data to pipe.
When I terminate the command ffmpeg shows that it read some data but couldn't process it.
Here's the function that produces that error:
void AVIFileSink::setWord(unsigned filePosn, unsigned size) {
do {
if (SeekFile64(fOutFid, filePosn, SEEK_SET) < 0) break;
addWord(size);
if (SeekFile64(fOutFid, 0, SEEK_END) < 0) break; // go back to where we were
return;
} while (0);
// One of the SeekFile64()s failed, probable because we're not a seekable file
envir() << "AVIFileSink::setWord(): SeekFile64 failed (err "
<< envir().getErrno() << ")\n";
}
In my opinion it looks like it won't be able to seek file because it's a stream not a static file.
Any suggestion for a workaround?