I am creating a flask application with JavaScript to save the live video streams to a file.
What I am trying to achieve here is that, the video stream will be sent to flask application periodically (20 secs). The first time it will create a video and after that, the video needs to be merged to the existing file.
I am using SocketIO to transmit the video from JS.
`async function startCapture() {
try {
// Access the user's webcam
stream = await navigator.mediaDevices.getUserMedia({
video: true,
audio: { echoCancellation: true, noiseSuppression: true },
});
// Attach the stream to the video element
video.srcObject = stream;
// Create a new MediaRecorder instance to capture video chunks
recorder = new MediaRecorder(stream);
// Event handler for each data chunk received from the recorder
recorder.ondataavailable = (e) => {
const videoBlob = e.data;
transmitVideoChunk(videoBlob);
chunks.push(e.data);
};
// Start recording the video stream
recorder.start();
// Enable/disable buttons
startButton.disabled = true;
stopButton.disabled = false;
// Start transmitting video chunks at the desired fps
startTransmitting();
} catch (error) {
console.error('Error accessing webcam:', error);
}
}`
`
function transmitVideoBlob() {
const videoBlob = new Blob(chunks, { type: 'video/webm' });
socket.emit('video_data', videoBlob);
// Clear the chunks array
chunks = [];
}
// Start transmitting video chunks at the desired fps
function startTransmitting() {
const videoInterval = 20000; // Interval between frames in milliseconds
videoIntervalId = setInterval(() => {
transmitVideoBlob();
}, videoInterval);
}`
In flask, I have created a function, which will call create_videos. video_path: location to save the video filename: file name of video new_video_data_blob: binary data received from JS
def create_videos(video_path, filename, new_video_data_blob):
chunk_filename = os.path.join(video_path, f"{str(uuid1())}_{filename}")
final_filename = os.path.join(video_path, filename)
out_final_filename = os.path.join(video_path, "out_" + filename)
# Save the current video chunk to a file
with open(chunk_filename, "wb") as f:
print("create file chunk ", chunk_filename)
f.write(new_video_data_blob)
if not os.path.exists(final_filename):
# If the final video file doesn't exist, rename the current chunk file
os.rename(chunk_filename, final_filename)
else:
while not os.path.exists(chunk_filename):
time.sleep(0.1)
# If the final video file exists, use FFmpeg to concatenate the current chunk with the existing file
try:
subprocess.run(
[
"ffmpeg",
"-i",
f"concat:{final_filename}|{chunk_filename}",
"-c",
"copy",
"-y",
out_final_filename,
]
)
while not os.path.exists(out_final_filename):
time.sleep(0.1)
os.remove(final_filename)
os.rename(out_final_filename, final_filename)
except Exception as e:
print(e)
# Remove the current chunk file
os.remove(chunk_filename)
return final_filename
When I record as well using below code in JS
audio: { echoCancellation: true, noiseSuppression: true },
I get the following error.
[NULL @ 0x55e697e8c900] Invalid profile 5.
[webm @ 0x55e697ec3180] Non-monotonous DTS in output stream 0:0; previous: 37075, current: 37020; changing to 37075. This may result in incorrect timestamps in the output file.
[NULL @ 0x55e697e8d8c0] Error parsing Opus packet header.
Last message repeated 1 times
[NULL @ 0x55e697e8c900] Invalid profile 5.
[NULL @ 0x55e697e8d8c0] Error parsing Opus packet header.
But when I record video only, it will work fine.
How can I merge the new binary data to the existing video file?
from Python Flask: Saving live stream video to a file periodically

No comments:
Post a Comment