I have a lesson with javascript for beginner, and i have an issue with the API "post " function. I don’t understand why my code doesn’t run because with the get method, my code runs well. The aim is to post a new work (new image with title and catégory) or is to publish changement. There is my javascript code. If you see an error, please tell me. Thank a lot.
And the error message in console : enter image description here
here is my repo github :
enter link description here
Here is my javascript code :
/* Send the image to server */
let image;
const submitButton = document.querySelector("#submit-button");
const titleInput = document.querySelector("#title");
const categorySelect = document.querySelector("#category");
const background = document.querySelector(".background");
const img = document.createElement("img");
submitButton.addEventListener("click", function(event) {
event.preventDefault();
const title = titleInput.value;
const category = categorySelect.value;
console.log(image);
if (!title || !category) {
console.error("les champs sont tous requis");
return;
}
if (!image) {
console.error("Une image est obligatoire");
}
const formData = new FormData();
formData.append("image", image, image.name);
formData.append("title", title);
formData.append("category", category);
try {
const response = fetch("http://localhost:5678/api/works", {
method: "POST",
headers: {
"Content-Type": "application/json",
"Authorization": `Bearer ${sessionStorage.token}`
},
body: formData
});
submitButton.style.backgroundColor = "#1D6154";
}
catch (error) {
console.error(error);
submitButton.style.backgroundColor = "#A7A7A7";
}
});
/* upload an image */
let imgSrc;
document.querySelector(".add-photo").addEventListener("click", function() {
const input = document.createElement("input");
input.type = "file";
input.accept = "image/jpg, image/png";
input.click();
/* Check the file type and size */
input.addEventListener("change", async function() {
image = input.files[0];
if (image.type !== "image/jpg" && image.type !== "image/png") {
document.getElementById("errorMessage").innerHTML = "jpg ou png obligatoire";
return;
}
if (image.size > 4 * 1024 *1024) {
document.getElementById("errorMessage").innerHTML = "4mo maximum";
return;
}
/* Replace by image loaded, the default message jpg png 4mo max */
background.innerHTML = "";
const reader = new FileReader();
reader.readAsDataURL(image);
reader.onload = function() {
img.src = reader.result;
imgSrc = reader.result;
img.style.width = "30%";
background.appendChild(img);
if (titleInput.value && categorySelect.value && img.src) {
submitButton.disabled = false;
}
else {
submitButton.disabled = true;
}
}
});
});
/* take categories from API in loading new image*/
async function getCategories() {
const response = await fetch("http://localhost:5678/api/categories");
const categories = await response.json();
const select = document.querySelector("#category");
for (let i = 0; i < categories.length; i++) {
let option = document.createElement("option");
option.value = categories[i].id;
option.innerHTML = categories[i].name;
select.appendChild(option);
}
}
getCategories();
/* function submit button valider */
function validate() {
if (titleInput.value && categorySelect.value && img.src) {
submitButton.disabled = false;
}
else {
submitButton.disabled = true;
}
}
titleInput.addEventListener("input", validate);
categorySelect.addEventListener("input", validate);
validate();
/* publish all work on index.html */
const publish = document.querySelector(".publish");
publish.addEventListener("click", function() {
console.log("publish");
const portfolio = document.getElementById("portfolio");
portfolio.innerHTML = "";
fetch("http://localhost:5678/api/works", {
method: "POST",
headers: {
"Content-Type": "application/json",
"Authorization": `Bearer ${sessionStorage.token}`
},
body: JSON.stringify({
title: titleInput.value,
category: categorySelect.value,
image: imgSrc
})
})
.then(function (response) {
return response.json();
})
.then(function (work) {
displayPortfolio(work);
})
.catch(function (error) {
console.error(error);
});
});
Related
I am trying to integrate stripe recurring payment into velo Wix X editor I am getting the below error.
I replace plan id with price id it seems but when i try test it generate the following below error does any have the same issue ? Please help
{
"error": "Received unknown parameter: source",
"code": "parameter_unknown",
"type": "invalid_request_error"
}
Here is my code snippet
Front End code
import { createTokenrec, encodeCardrec } from "public/recuringpayment.js";
import { subscription, createCustomer } from "backend/backendStriperRec"
$w.onReady(function () {
var items = ['price_1M5d3tEdzfbM5fq7RHYhSc5x']; //your plan ID will go here (plan_XXXXXXXXXXXXXX)
var customer ='user';
$w('#recfirstStep').onClick((event) => {
var errorChekRec = 0
var Rfname = $w('#Rfname');
var Rlname = $w('#Rlname');
var Rphone = $w('#Rphone');
var Remail = $w('#Remail');
var Rfilter = /^([a-zA-Z0-9_\.\-])+\#(([a-zA-Z0-9\-])+\.)+([a-zA-Z0-9]{2,4})+$/;
if (Rfname.value == "") {
$w('#Rerror').show();
$w('#Rerror').text = "Please enter your first name";
errorChekRec = 1;
Rfname.focus();
return false;
}
if (Rlname.value == "") {
$w('#Rerror').show();
$w('#Rerror').text = "Please enter your Last name";
errorChekRec = 1;
Rlname.focus();
return false;
}
if (Rphone.value == "") {
$w('#Rerror').show();
$w('#Rerror').text = "Please enter your phone";
errorChekRec = 1;
Rphone.focus();
return false;
}
if (!Rfilter.test(Remail.value)) {
$w('#Rerror').show();
$w('#errorf').text = "Please put valid email";
errorChekRec = 1;
Remail.focus();
return false;
}
if (!$w("#Rterms").checked) {
$w('#Rerror').show();
$w('#Rerror').text = "You missed to agree with our term and conditions ";
$w('#Rterms').focus();
console.log('checkbox console.error();')
errorChekRec = 1;
$w('#Rterms').style.backgroundColor = 'red';
}
if (errorChekRec == 0) {
$w('#Rerror').hide();
$w('#recslides').changeState('recsec')
customer = $w("#Remail").value;
console.log('next step')
var date = (new Date()).toISOString().split('T')[0];
$w('#Rdatetime').html = '<span style=" font-weight: bolder;font-size: 14px;">Order Date: ' + date + '</span>';
$w("#Rdemail").html = "Delivery: " + $w('#email').value;
}
});
$w('#recfirstrev').onClick((event) => {
$w('#recslides').changeState('recfirst')
});
function payNowRecu() {
var accepted = false;
var errorTokenRec = 0;
if ($w('#Rcard').value.length > 16 || $w('#Rcard').value.length < 10) {
$w('#Rcard').style.borderColor = 'red';
errorTokenRec = 1;
$w('#Rcard').focus();
}
if ($w("#Rcvv").value == "") {
errorTokenRec = 1;
$w('#Rcvv').style.borderColor = 'red';
$w('#Rcvv').focus();
}
if ($w("#Ryear").value == "") {
$w('#Ryear').focus();
errorTokenRec = 1;
$w('#Ryear').style.borderColor = 'red';
}
if ($w("#Rmonth").value == "") {
errorTokenRec = 1;
$w('#Rmonth').focus();
$w('#Rmonth').style.borderColor = 'red';
}
function createCardrec() {
return {
"name": 'Suleman khan',//$w("#Rfname").value + " " + $w("#Rlname").value,
"number": '4242424242424242',//$w("#Rcard").value,
"cvc": '223',//$w("#Rcvv").value,
"exp_year": '2024',//$w("#Ryear").value,
"exp_month": '12',// $w("#Rmonth").value
};
}
console.log(createCardrec())
if (errorTokenRec != 1) {
console.log('procced')
var itemsArray = [];
createTokenrec(encodeCardrec(createCardrec())) //we start the process by encoding the card and creating a token
.then((token) => {
createCustomer(customer) //create a new customer
.then((id) => {
let itemsArray = {
"customer": 'cus_MqN6xtdzFNr9RS', //this is your customer ID
"items[0][plan]": 'price_1M6gEREdzfbM5fq7qAJwYDnE' //this is your plan id
};
subscription(token, itemsArray) //subscribe
.then((response) => {
console.log(response.chargeId)
console.log(response)
if (response.chargeId !== undefined) {
accepted = true;
console.log(response)
// wixLocation.to('/success'); //redirect on success
} else {
$w("#Rcarderror").text = response.error; //show error message on failure
}
});
console.log(token);
});
});
}
}
$w('#PayOntimeNow').onClick((event) => {
payNowRecu(); //start payment (you will need a button)
})
})
Backend Code
import {fetch} from 'wix-fetch';
export async function subscription(token, item) {
const cart = item;
const apiKey = "secret key";
const response = await fetch("https://api.stripe.com/v1/subscriptions", {
method: 'post',
headers: {
"Content-Type": "application/x-www-form-urlencoded",
"Authorization": "Bearer " + apiKey
},
body: encodeBody(token, cart)
});
if (response.status >= 200 && response.status < 300) {
// transaction successful - get charge ID
const ret = await response.json();
return {"chargeId": ret.id};
}
// transaction failed - return error messages and codes
let res = await response.json();
let err = res.error.message;
let code = res.error.code;
let type = res.error.type;
return {"error": err, "code": code, "type": type};
}
function encodeBody(token, cart) {
let encoded = "";
for (let [k, v] of Object.entries(cart)) {
encoded = encoded.concat(k,"=", encodeURI(v), "&");
}
encoded = encoded.concat("source=", encodeURI(token));
return encoded;
}
//Creating a customer
export async function createCustomer(customer) {
const client = String(customer);
const apiKey = "Secret key";
const response = await fetch("https://api.stripe.com/v1/customers", {
method: 'post',
headers: {
"Content-Type": "application/x-www-form-urlencoded",
"Authorization": "Bearer " + apiKey
},
body: encodeClient(client)
});
if (response.status >= 200 && response.status < 300) {
const json = await response.json();
return json.id;
}
const responseText = await response.text();
return response.status;
}
function encodeClient(client){
let encoded = "";
encoded = encoded.concat("email=", encodeURI(client));
return encoded;
}
Linked javascript client side file
import {fetch} from 'wix-fetch';
export async function createTokenrec(card) {
const apiKey = "Publish key";
const response = await fetch("https://api.stripe.com/v1/tokens", {
method: 'post',
headers: {
"Content-Type": "application/x-www-form-urlencoded",
"Authorization": "Bearer " + apiKey
},
body: card
});
if (response.status >= 200 && response.status < 300) {
const json = await response.json();
return json.id;
}
const responseText = await response.text();
return response.status;
console.log(response)
}
export function encodeCardrec(card){
let encoded = "";
for (let [k, v] of Object.entries(card)) {
encoded = encoded.concat("card[", k, "]=", encodeURI(v), "&");
}
return encoded.substr(0, encoded.length - 1);
}
Screenshot of error:
So, basically i'm getting this weird error in my java Script file, called: Failed to fetch
at sendData
and i don't know quite what is the error, i cant save nothing to my database cause of this error
here's the code from the form.js :
const loader = document.querySelector('.loader');
// select inputs
const SubmitBtn = document.querySelector('.submit-btn');
const name = document.querySelector('#name');
const email = document.querySelector('#email');
const password = document.querySelector('#password');
const number = document.querySelector('#number');
const tac = document.querySelector('#terms-and-cond');
const notification = document.querySelector('#notification');
SubmitBtn.addEventListener('click', () => {
if (name.value.length < 3) {
showAlert('name must be 3 letters long');
} else if (!email.value.length) {
showAlert('enter your email');
} else if (password.value.length < 8) {
showAlert('password should be 8 letters long');
} else if (!number.value.length) {
showAlert('enter your phone number');
} else if (!Number(number.value) || number.value.length < 10) {
showAlert('invalid number, please enter a valid one');
} else if (!tac.checked) {
showAlert('you must agree to our terms and conditions')
} else {
// submeter o form
loader.style.display = 'block';
sendData('/signup', {
name: name.value,
email: email.value,
password: password.value,
number: number.value,
tac: tac.checked,
notification: notification.checked,
seller: false
})
}
})
// send data function
const sendData = (path, data) => {
fetch(path, {
method: 'post',
headers: new Headers({
'Content-Type': 'application/json'
}),
body: JSON.stringify(data)
}).then((res) => res.json())
.then(response => {
processData(response);
})
}
const processData = (data) => {
loader.style.display = null;
if (data.alert) {
showAlert(data.alert);
}
}
// alert funcionalidade
const showAlert = (msg) => {
let alertBox = document.querySelector('.alert-box');
let alertMsg = document.querySelector('.alert-msg');
alertMsg.innerHTML = msg;
alertBox.classList.add('show');
setTimeout(() => {
alertBox.classList.remove('show');
}, 3000);
}
with this i always get the same error, it doesn't save the users to the database, and its kinda irritating. i would like help for this type of error as soon as possible. this for a school project and time is coming short...
I am working on a video recording task using MediaRecorder API. As from frontend I can start the webcam, record video, play the recorded video and download the video.
But when I try to upload the video to php server, it's not at all working. I don't really understand why it is happening, I also tried using so many methods but none of it is working. Please check the code attatched below.
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');
document.querySelector("button#start").addEventListener("click", async function() {
const hasEchoCancellation = document.querySelector("#echoCancellation").checked
const constraints = {
audio: {
echoCancellation:{
exact: hasEchoCancellation
}
},
video: {
width: 1280,
height: 720
}
}
await init(constraints)
})
async function init(constraints) {
try {
const stream = await navigator.mediaDevices.getUserMedia(constraints)
handleSuccess(stream)
} catch(e) {
console.log(e)
}
}
function handleSuccess(stream) {
recordButton.disabled = false
window.stream = stream
const gumVideo = document.querySelector("video#gum")
gumVideo.srcObject = stream
}
recordButton.addEventListener("click", () => {
if(recordButton.textContent === "Record") {
startRecording()
} else {
stopRecording()
recordButton.textContent = 'Record'
playButton.disabled = false
downloadButton.disabled = false
}
})
function startRecording() {
recordedBlobs = []
let options = {
mimeType: "video/webm;codecs=vp9,opus"
}
try {
mediaRecorder = new MediaRecorder(window.stream, options)
} catch(e) {
console.log(e)
}
recordButton.textContent = "Stop Recording"
playButton.disabled = true
downloadButton.disabled = true
mediaRecorder.onstop = (event) => {
console.log('Recording Stopped')
}
mediaRecorder.ondataavailable = handleDataAvailable
mediaRecorder.start()
}
function handleDataAvailable(event) {
if(event.data && event.data.size > 0) {
recordedBlobs.push(event.data)
}
}
function stopRecording() {
mediaRecorder.stop()
}
playButton.addEventListener('click', function() {
const superBuffer = new Blob(recordedBlobs, {
type: 'video/webm'
})
var file = new File([superBuffer], 'test.webm')
var url = window.URL.createObjectURL(superBuffer)
// var video = blobToFile(superBuffer, 'test.webm')
sendToServer(file)
recordedVideo.src = null
recordedVideo.srcObject = null
recordedVideo.src = url
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 = 'test.mp4';
document.body.appendChild(a);
a.click();
setTimeout(() => {
document.body.removeChild(a);
window.URL.revokeObjectURL(url);
}, 100);
});
function sendToServer(file) {
let url = 'send.php'
let headers = {
'Content-Type': 'multipart/form-data'
}
var formData = new FormData()
formData.append("file", file)
axios.post(url, formData, headers)
.then((response) => {
console.log(response.data)
})
.catch((error) => {
console.log(error.response)
})
}
function blobToFile(theBlob, fileName){
//A Blob() is almost a File() - it's just missing the two properties below which we will add
theBlob.lastModifiedDate = new Date();
theBlob.name = fileName;
return theBlob;
}
PHP:-
$target_dir = "uploads/";
$target_file = $target_dir . 'test.webm';
if(move_uploaded_file($_FILES["file"]["tmp_name"], $target_file)) {
echo "File uploaded successfully";
} else {
echo "File not uploaded";
}
print_r($_FILES['file']['error']);
No matter how much I tried, I can't figure out why it is not working. It is showing that "File not uploaded" like it can't read the file from tmp_name. Please help me fix the problem.
Any help on this problem will be really appreciated.
Thank you.
I have a function that adds an item to a list and a function that deletes an item. When I add the item it displays correctly but the item cannot be deleted until I refresh the page. I'm using python 3, flask and javascript but I don't know why the delete function cannot be called on the newly created item. This is the relevant code:
index.html:
const checkboxes = document.querySelectorAll('.check-completed');
for (let i = 0; i < checkboxes.length; i++) {
const checkbox = checkboxes[i];
checkbox.onchange = function(e) {
console.log('click')
const newCompleted = e.target.checked;
const todoId = e.target.dataset['id'];
fetch('/todos/' + todoId + '/set-completed', {
method: 'POST',
body: JSON.stringify({
'completed': newCompleted
}),
headers: {
'Content-Type': 'application/json'
}
})
.then(function() {
document.getElementById('error').className = 'hidden';
})
.catch(function() {
document.getElementById('error').className = '';
})
}
}
const descInput = document.getElementById('description');
document.getElementById('form').onsubmit = function(e) {
e.preventDefault();
const desc = descInput.value;
descInput.value = '';
fetch('/todos/create', {
method: 'POST',
body: JSON.stringify({
'description': desc,
}),
headers: {
'Content-Type': 'application/json',
}
})
//.then(response => {
// return response.json()
// data = response.json()
//})
.then(response => response.json())
.then(jsonResponse => {
const li = document.createElement('li');
const checkbox = document.createElement('input');
checkbox.className = 'check-completed';
checkbox.type = 'checkbox';
checkbox.setAttribute('data-id', jsonResponse.id);
li.appendChild(checkbox);
const text = document.createTextNode(' ' + jsonResponse.description);
li.appendChild(text);
const deleteBtn = document.createElement('button');
deleteBtn.className = 'xbox';
deleteBtn.setAttribute('data-id', jsonResponse.id);
deleteBtn.innerHTML = '✗';
li.appendChild(deleteBtn);
document.getElementById('todos').appendChild(li);
document.getElementById('error').className = 'hidden';
})
.catch(function() {
console.error('Error occurred');
document.getElementById('error').className = '';
})
}
Delete code
const deletes = document.querySelectorAll('.xbox');
for (let i = 0; i < deletes.length; i++) {
const btn = deletes[i];
btn.onclick = function(e) {
console.log('click')
const todoId = e.target.dataset['id'];
fetch('/todos/' + todoId, {
method: 'DELETE'
})
.then(function() {
const item = e.target.parentElement;
item.remove();
})
}
}
app.py
#app.route('/todos/create', methods=['POST'])
def create_todo():
error = False
body = {}
# description = request.form.get('description', '')
# return render_template('index.html')
try:
description = request.get_json()['description']
todo = Todo(description=description)
#body['description'] = todo.description
db.session.add(todo)
db.session.commit()
body['id'] = todo.id
body['completed'] = todo.completed
body['description'] = todo.description
except:
error=True
db.session.rollback()
print(sys.exc_info())
finally:
db.session.close()
if error:
abort (400)
else:
return jsonify(body)
I got it. I had to name the update and delete functions and call them inside the add item function to attach the functions to the new css elements.
Am recording video using webrtc and send each 10 seconds video as blob to server, and all 10 seconds files are getting saved on server, till now everything is fine but only problem is only first video file is getting played as video rest other files are not getting played since it is missing codec and MIMEType. please help me how to send each 10 seconds blob with mimetype and wit codec vp9
// This code is adapted from
// https://rawgit.com/Miguelao/demos/master/mediarecorder.html
'use strict';
/* globals MediaRecorder */
const mediaSource = new MediaSource();
mediaSource.addEventListener('sourceopen', handleSourceOpen, false);
let mediaRecorder;
let recordedBlobs;
let sourceBuffer;
const errorMsgElement = document.querySelector('span#errorMsg');
const recordedVideo = document.querySelector('video#recorded');
const recordButton = document.querySelector('button#record');
recordButton.addEventListener('click', () => {
if (recordButton.textContent === 'Start Recording') {
startRecording();
} else {
stopRecording();
recordButton.textContent = 'Start Recording';
playButton.disabled = false;
downloadButton.disabled = false;
}
});
const playButton = document.querySelector('button#play');
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();
console.log('start- display recordedblob');
console.log(recordedVideo);
console.log('end- display recordedblob');
});
const downloadButton = document.querySelector('button#download');
downloadButton.addEventListener('click', () => {
const blob = new Blob(recordedBlobs, {type: 'video/webm'});
const url = window.URL.createObjectURL(blob);
const a = document.createElement('a');
a.style.display = 'none';
a.href = url;
a.download = 'test.webm';
document.body.appendChild(a);
a.click();
setTimeout(() => {
document.body.removeChild(a);
window.URL.revokeObjectURL(url);
}, 100);
});
function handleSourceOpen(event) {
console.log('MediaSource opened');
sourceBuffer = mediaSource.addSourceBuffer('video/webm; codecs="vp8"');
console.log('Source buffer: ', sourceBuffer);
}
function handleDataAvailable(event) {
console.log('handleDataAvailable', event);
console.log('shree sai baba', event.data);
if (event.data && event.data.size > 0) {
recordedBlobs.push(event.data);
console.log('heyy'+recordedBlobs);
// to save video as each blob
var formData = new FormData();
formData.append('video', event.data);
console.log('result blob which am trying to send to server', event.data);
// Execute the ajax request, in this case we have a very simple PHP script
// that accepts and save the uploaded "video" file
xhr('/webcam/', formData, function (fName) {
console.log("video successfully uploaded !");
});
// Helper function to send
function xhr(url, data, callback) {
var request = new XMLHttpRequest();
request.onreadystatechange = function () {
if (request.readyState == 4 && request.status == 200) {
callback(location.href + request.responseText);
}
};
request.open('POST', url);
request.send(data);
console.log(data);
console.log('logg')
console.log(request.response);
}
console.log('10 seconds video sent to the server');
// end of save video as each
}
}
function startRecording() {
recordedBlobs = [];
let options = {mimeType: 'video/webm;codecs=vp9'};
if (!MediaRecorder.isTypeSupported(options.mimeType)) {
console.error(`${options.mimeType} is not Supported`);
errorMsgElement.innerHTML = `${options.mimeType} is not Supported`;
options = {mimeType: 'video/webm;codecs=vp8'};
if (!MediaRecorder.isTypeSupported(options.mimeType)) {
console.error(`${options.mimeType} is not Supported`);
errorMsgElement.innerHTML = `${options.mimeType} is not Supported`;
options = {mimeType: 'video/webm'};
if (!MediaRecorder.isTypeSupported(options.mimeType)) {
console.error(`${options.mimeType} is not Supported`);
errorMsgElement.innerHTML = `${options.mimeType} is not Supported`;
options = {mimeType: ''};
}
}
}
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('naduuuuuuuuuuuuuuuuuuuuzz');
console.log('Recorded Blobss: ', recordedBlobs);
console.log('ans', recordedBlobs);
// console.log(Blob.arrayBuffer())
console.log('Recorded Blobss: ', recordedBlobs.type);
console.log('naduuuuuuuuuuuuuuuuuuuu');
};
mediaRecorder.ondataavailable = handleDataAvailable;
mediaRecorder.start(10000); // collect 10s of data
console.log('MediaRecorder started', mediaRecorder);
}
function stopRecording() {
mediaRecorder.stop();
}
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: 720, height: 480
}
};
console.log('Using media constraints:', constraints);
await init(constraints);
});
request.setRequestHeader('Content-Type', 'video/webm');