I’m attempting to record a video and download it with a border. I’m using the RGB color values 0, 0, 255 for the border. While I can easily download the recorded video, the border does not appear on it. When I click on the ‘Start Recording’ button, recording is initiated. Upon clicking the ‘Stop Recording’ button, a download button appears containing the link to download the video. However, the downloaded video lacks the border.
APP.PY
from flask import Flask, render_template, send_file
import cv2
import numpy as np
app = Flask(__name__)
@app.route('/')
def index():
return render_template('index.html')
def add_border_to_video(video_path, output_path, border_thickness=20, border_color=(0, 0, 255)):
cap = cv2.VideoCapture(video_path)
frame_width = int(cap.get(cv2.CAP_PROP_FRAME_WIDTH))
frame_height = int(cap.get(cv2.CAP_PROP_FRAME_HEIGHT))
fourcc = cv2.VideoWriter_fourcc(*'mp4v')
out = cv2.VideoWriter(output_path, fourcc, 20.0, (frame_width, frame_height))
while True:
ret, frame = cap.read()
if not ret:
break
# Add border to the frame
bordered_frame = cv2.copyMakeBorder(frame, border_thickness, border_thickness, border_thickness, border_thickness, cv2.BORDER_CONSTANT, value=border_color)
out.write(bordered_frame)
cap.release()
out.release()
@app.route('/record_video')
def record_video():
# Record video with OpenCV
# Make sure to save it to a file
# For simplicity, let's assume the file is named 'recorded_video.mp4'
recorded_video_path = 'recorded_video.mp4'
# Add border to the recorded video
bordered_video_path = 'output_with_border.mp4'
add_border_to_video(recorded_video_path, bordered_video_path)
return 'Video recorded and bordered successfully!'
@app.route('/download_video')
def download_video():
# Serve the bordered video file for download
bordered_video_path = 'output_with_border.mp4'
return send_file(bordered_video_path, as_attachment=True)
if __name__ == '__main__':
app.run(debug=True)
INDEX.HTML (HTML AND JS)
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Record and Download Video</title>
<style>
/* CSS styles for the video container */
#video-container {
width: 640px;
height: 480px;
margin: 0 auto;
border: 2px solid black;
}
</style>
</head>
<body>
<h1>Record and Download Video</h1>
<!-- Video container -->
<div id="video-container">
<video id="video" width="640" height="480" autoplay></video>
</div>
<!-- Buttons for recording and downloading -->
<button id="startRecord">Start Recording</button>
<button id="stopRecord" disabled>Stop Recording</button>
<a id="downloadVideo" style="display: none;">Download Video</a>
<!-- JavaScript code -->
<script>
const video = document.getElementById('video');
const startRecordBtn = document.getElementById('startRecord');
const stopRecordBtn = document.getElementById('stopRecord');
const downloadVideoBtn = document.getElementById('downloadVideo');
let mediaRecorder;
let chunks = [];
startRecordBtn.addEventListener('click', async () => {
try {
const stream = await navigator.mediaDevices.getUserMedia({ video: true });
video.srcObject = stream;
startRecordBtn.disabled = true;
stopRecordBtn.disabled = false;
downloadVideoBtn.style.display = 'none';
mediaRecorder = new MediaRecorder(stream);
mediaRecorder.ondataavailable = handleDataAvailable;
mediaRecorder.start();
} catch (err) {
console.error('Error accessing camera:', err);
}
});
stopRecordBtn.addEventListener('click', () => {
mediaRecorder.stop();
startRecordBtn.disabled = false;
stopRecordBtn.disabled = true;
});
function handleDataAvailable(event) {
chunks.push(event.data);
if (mediaRecorder.state === 'inactive') {
const blob = new Blob(chunks, { type: 'video/mp4' });
const url = URL.createObjectURL(blob);
downloadVideoBtn.href = url;
downloadVideoBtn.download = 'recorded_video.mp4';
downloadVideoBtn.style.display = 'inline';
}
}
</script>
</body>
</html>
2
Answers
This aim to be a minimal example with focus on how and where pre– and post-process a video. No JavaScript is needed.
Due to the huge amount of online tutorial copying each other out I tried to give an "improved" version and also use coroutines to better separate the tasks of pre and post processing.
Once opening the root page, for ex
localhost:5000/
, the the camera will be turned on and automatically the video will be recorder. For stop the recording close the window (or partially reload the page).Notice further that in the OP there is a mistake when the writer is initialised: by adding a border to the frames their size change as well
out = cv2.VideoWriter( [...], (frame_width + 2*border_thickness, frame_height+2*border_thickness))
.Your code for adding a border doesn’t take into account that the border makes the individual frame of the video larger. For this reason, the edited video cannot be played.
You also added the URL of the unedited video to the download button. The original is never sent to the server. Because of this, the code to add the border is not executed and the border is also not visible in the downloaded video.
The following example shows you how to record a video on the client side and send it to the server where it is edited. The edited video is then offered for download.