Issue
I'm working on a site where users can make a video from themselves. I'm using Django but I'm not so familiar with advanced JavaScript. I'm using JavasScript code to record the video which is not my code I found it. It works well and downloads the recorded video but I like to save the video to my filesystem instead of download and upload manually or send it to a fileinput with the /documents/videointerview path to save. Also I like to save it to my database if I click to Download button.
html
<div id="container mx-auto">
<video id="gum" class="mx-auto w-50 d-flex justify-content-center" autoplay muted></video>
<video id="recorded" class="mx-auto w-50 d-flex justify-content-center" playsinline loop></video>
<div class="my-5">
<button class="btn btn-primary" id="start">Start camera</button>
<button class="btn btn-success" id="record" disabled>Record</button>
<button class="btn btn-warning" id="play" disabled>Play</button>
<button class="btn btn-secondary" id="download" disabled>Download</button>
</div>
<div class="m-3">
<h4 class="text-info">Video Stream Options</h4>
<div class="form-check form-switch">
<input class="form-check-input" type="checkbox" id="echoCancellation">
<label class="form-check-label text-center" for="flexSwitchCheckDefault">Echo Cancellation</label>
</div>
</div>
<div>
<span id="errorMsg"></span>
</div>
</div>
<form method="post" enctype="multipart/form-data">
{% csrf_token %}
{{ form.as_p }}
<button type="submit" class="btn btn-primary">Save</button>
</form>
js
let mediaRecorder;
let recordedBlobs;
const errorMsgElement = document.querySelector('span#errorMsg');
const recordedVideo = document.querySelector('video#recorded');
const recordButton = document.querySelector('button#record');
const playButton = document.querySelector('button#play');
const downloadButton = document.querySelector('button#download');
recordButton.addEventListener('click', () => {
if (recordButton.textContent === 'Record') {
startRecording();
} else {
stopRecording();
recordButton.textContent = 'Record';
playButton.disabled = false;
downloadButton.disabled = false;
}
});
playButton.addEventListener('click', () => {
const superBuffer = new Blob(recordedBlobs, {type: 'video/webm'});
recordedVideo.src = null;
recordedVideo.srcObject = null;
recordedVideo.src = window.URL.createObjectURL(superBuffer);
recordedVideo.controls = true;
recordedVideo.play();
});
downloadButton.addEventListener('click', () => {
const blob = new Blob(recordedBlobs, {type: 'video/mp4'});
const url = window.URL.createObjectURL(blob);
const a = document.createElement('a');
a.style.display = 'none';
a.href = url;
a.download = 'w3-coder-recorder-test.mp4';
document.body.appendChild(a);
a.click();
setTimeout(() => {
document.body.removeChild(a);
window.URL.revokeObjectURL(url);
}, 100);
});
function handleDataAvailable(event) {
console.log('handleDataAvailable', event);
if (event.data && event.data.size > 0) {
recordedBlobs.push(event.data);
}
}
async function myvideo() {
const returnedData= await a;
console.log(returnedData);
document.getElementById('wtf').innerHTML = returnedData;
}
function startRecording() {
recordedBlobs = [];
let options = {mimeType: 'video/webm;codecs=vp9,opus'};
try {
mediaRecorder = new MediaRecorder(window.stream, options);
} catch (e) {
console.error('Exception while creating MediaRecorder:', e);
errorMsgElement.innerHTML = `Exception while creating MediaRecorder: ${JSON.stringify(e)}`;
return;
}
console.log('Created MediaRecorder', mediaRecorder, 'with options', options);
recordButton.textContent = 'Stop Recording';
playButton.disabled = true;
downloadButton.disabled = true;
mediaRecorder.onstop = (event) => {
console.log('Recorder stopped: ', event);
console.log('Recorded Blobs: ', recordedBlobs);
};
mediaRecorder.ondataavailable = handleDataAvailable;
mediaRecorder.start();
console.log('MediaRecorder started', mediaRecorder);
}
function stopRecording() {
mediaRecorder.stop();
//const baseUrl='/documents/videointerviews/';
//const fileName =`${baseUrl}${{request.user}}`;
//globalBlob = new Blob(recordedBlobs, {type: 'video/mp4',fileName});
//console.log(globalBlob);
// const url = window.URL.createObjectURL(globalBlob);
//globalBlob.sendToFileSystem().then(response=>{
//const url = response.url;
// return url;
//}).then(secondaryReponse=>{
//secondaryReponse.sendUrlToDb
//})
}
function handleSuccess(stream) {
recordButton.disabled = false;
console.log('getUserMedia() got stream:', stream);
window.stream = stream;
const gumVideo = document.querySelector('video#gum');
gumVideo.srcObject = stream;
}
async function init(constraints) {
try {
const stream = await navigator.mediaDevices.getUserMedia(constraints);
handleSuccess(stream);
} catch (e) {
console.error('navigator.getUserMedia error:', e);
errorMsgElement.innerHTML = `navigator.getUserMedia error:${e.toString()}`;
}
}
document.querySelector('button#start').addEventListener('click', async () => {
const hasEchoCancellation = document.querySelector('#echoCancellation').checked;
const constraints = {
audio: {
echoCancellation: {exact: hasEchoCancellation}
},
video: {
width: 480, height: 320
}
};
console.log('Using media constraints:', constraints);
await init(constraints);
});
views.py
@login_required
def video_interview(request, company_uuid, position_id, position_slug):
ruser = request.user.id
position = Position.objects.filter(id=position_id, position_slug=position_slug)
if request.method == 'POST':
form = VideoInterviewUploadForm(request.POST, request.FILES)
form.instance.candidate = request.user
if form.is_valid():
form.instance.candidate = request.user
form.save()
return redirect('/mpa/main')
else:
form = VideoInterviewUploadForm()
context = {
'form': form,
'position': position,
}
return render(request, 'myway/video_interview.html', context)
forms.py
class VideoInterviewUploadForm(forms.ModelForm):
class Meta:
model = VideoInterview
fields = ('description', 'document', 'candidate',)
widgets = {
'candidate': forms.HiddenInput(),
'description': forms.HiddenInput(),
# 'document': forms.FileField(),
}
labels = {
'document': 'Interjú',
}
models.py
class VideoInterview(models.Model):
def __str__(self):
return str(self.candidate)
candidate = models.ForeignKey(User, on_delete=models.CASCADE, null=True, blank=True)
description = models.CharField(max_length=100, blank=True, verbose_name="Leírás")
document = models.FileField(upload_to='documents/videointerviews', verbose_name="CV")
datetime = models.DateTimeField(auto_now_add=True)
Solution
Do not use VideoInterviewUploadForm
for this. Use javascript Fetch API
Here we will upload to the server using Fetch API. We also add the CSRF Token
Javascript Code:
function getCookie(name) {
const value = `; ${document.cookie}`;
const parts = value.split(`; ${name}=`);
if (parts.length === 2) return parts.pop().split(';').shift();
}
async function upload(formData) {
try {
const response = await fetch("/video-app", {
method: "POST",
headers: {
"X-CSRFToken": getCookie('csrftoken'),
},
body: formData,
});
const result = await response.json();
console.log("Response:", result);
} catch (error) {
console.error("Error:", error);
}
}
downloadButton.addEventListener('click', () => {
const blob = new Blob(recordedBlobs, {type: 'video/mp4'});
// Upload to the server
const formData = new FormData();
formData.append("video", new File([blob], 'my-interview.mp4'));
upload(formData);
// Download for the client
const url = window.URL.createObjectURL(blob);
const a = document.createElement('a');
a.style.display = 'none';
a.href = url;
a.download = 'w3-coder-recorder-test.mp4';
document.body.appendChild(a);
a.click();
setTimeout(() => {
document.body.removeChild(a);
window.URL.revokeObjectURL(url);
}, 100);
});
Python code views.py:
@login_required
def video_interview(request):
if request.method == 'POST':
interview = request.FILES.get('video')
if interview is not None:
VideoInterview.objects.create(
candidate = request.user,
document = interview
)
return JsonResponse({'error_code': 0})
else:
return JsonResponse({'error_code': 1})
return render(request, 'test_app/video_app.html')
Also, your code doesn’t work for at least one modern browser. Tested with Firefox v120.0, I get an error:
navigator.getUserMedia error: DOMException: Starting videoinput failed
Sources:
Answered By - Zatigem
0 comments:
Post a Comment
Note: Only a member of this blog may post a comment.