ganjim
ganjim

Reputation: 1416

Dynamically record parts of a video stream using ffmpeg based on incoming events

Say I have a RTSP stream running on some server.

I want to record parts of this video stream based on some events that will come up on my machine. My goal is to record 10 seconds before up to 10 seconds after the PTS in any received event. Consider that I have a way to synchronize the PTS between the sender and the receiver, but by the time I receive the events, its already streamed and is in the past. So I either need to have the ffmpeg command running already, or to have buffered streaming video in my memory.

I just added some code with comments as a way to simulate the situation, it is not complete as I still don't have a working solution. But I'm looking to understand if ffmpeg has capabilities for dealing with rtsp streams suitable for this situation.

const { spawn } = require('child_process');

function processEvent(event){
  
  let startTime = event.pts - 10
  let endTime = event.pts + 10

  const ffmpegArgs = [
    '-i', "rtspUrl",
    '-ss', startTime.toString(),
    '-to', endTime.toString(),
    '-c', 'copy',
    '-f', 'mp4',
    `output_${startTime}_${endTime}.mp4` // Output filename
  ];
  // Here it is obviously not possible to give ffmpeg a negative startTime.
  // We either have to have spawned the ffmpeg command and somehow give it a starting time for recording on demand or have a buffering system in place.
  // Having a buffer to store every raw frame and then attach them after endTime is also considerably CPU and memory intensive.
  // Looking for alternative ways to achieve the same output.

  const ffmpegProcess = spawn('ffmpeg', ffmpegArgs, {
    stdio: 'inherit'
  });
}

// Code to simulate the events:
// imagine these pts to be relative to Date.now(), so using negative PTS to show the events are going to be in the past by the time we receive them.
setTimeout(() => {
  const event1= { pts: -30 };
  processEvent(event1);
}, 1000);

setTimeout(() => {
  const event2 = { pts: -20 };
  processEvent(event2);
}, 5000);

Upvotes: 1

Views: 597

Answers (1)

William McMillan
William McMillan

Reputation: 31

I actually have an interest in doing something similar, although driven by physical events, and recording "backwards" in time by X seconds before the event, and Y seconds after.

About the only reference I've ever found in my searches that even comes close is a workaround located here: https://trac.ffmpeg.org/wiki/Capture/Lightning

I haven't had a chance to try it myself yet.

Upvotes: 1

Related Questions