在 chrome 浏览器中使用 recordJs 库期间将定义的变量转换为未定义的
converting defined variable as undefined during using recordJs library in chrome browser
我正在使用 recordJs 库来录制客户端的语音并将其发送到服务器。在firefox等浏览器中运行良好,无任何错误。当我在 chrome 中尝试 运行 它时,它开始录制语音,但是当它调用 stopRecording 函数时,它面临以下错误:
Uncaught TypeError: Cannot read property 'stop' of undefined
at stopRecording (توانایی-پرسش-سن-از-افراد:1209)
at startTimer (توانایی-پرسش-سن-از-افراد:1364)
这是我的 JS 代码:
<script type="text/javascript">
'use strict';
//webkitURL is deprecated but nevertheless
URL = window.URL || window.webkitURL;
let gumStream; //stream from getUserMedia()
let rec; //Recorder.js object
let input; //MediaStreamAudioSourceNode we'll be recording
// shim for AudioContext when it's not avb.
let AudioContext = window.AudioContext || window.webkitAudioContext;
let audioContext //audio context to help us record
function startRecording() {
console.log("recordButton clicked");
/*
Simple constraints object, for more advanced audio features see
https://addpipe.com/blog/audio-constraints-getusermedia/
*/
var constraints = { audio: true, video:false }
/*
Disable the record button until we get a success or fail from getUserMedia()
*/
/*
We're using the standard promise based getUserMedia()
https://developer.mozilla.org/en-US/docs/Web/API/MediaDevices/getUserMedia
*/
navigator.mediaDevices.getUserMedia(constraints).then(function(stream) {
console.log("getUserMedia() success, stream created, initializing Recorder.js ...");
/*
create an audio context after getUserMedia is called
sampleRate might change after getUserMedia is called, like it does on macOS when recording through AirPods
the sampleRate defaults to the one set in your OS for your playback device
*/
audioContext = new AudioContext();
//update the format
// document.getElementById("formats").innerHTML="Format: 1 channel pcm @ "+audioContext.sampleRate/1000+"kHz"
/* assign to gumStream for later use */
gumStream = stream;
/* use the stream */
input = audioContext.createMediaStreamSource(stream);
/*
Create the Recorder object and configure to record mono sound (1 channel)
Recording 2 channels will double the file size
*/
rec = new Recorder(input,{numChannels:1});
//start the recording process
rec.record();
console.log("Recording started");
}).catch(function(err) {
});
}
function pauseRecording(){
console.log("pauseButton clicked rec.recording=",rec.recording );
if (rec.recording){
//pause
rec.stop();
}else{
rec.record();
}
}
function stopRecording() {
//tell the recorder to stop the recording
rec.stop();
//stop microphone access
gumStream.getAudioTracks()[0].stop();
//create the wav blob and pass it on to createDownloadLink
rec.exportWAV(setUserVoice);
}
function setUserVoice(blob)
{
let formData = new FormData
formData.append('userVoice', blob)
$.ajax({
type: 'POST',
headers: {'X-CSRF-TOKEN': $('meta[name="csrf-token"]').attr('content')},
url: '{{ route('user.mockTest.participation.saveUserVoice') }}',
data: formData,
processData: false,
contentType: false,
success: function (data) {
if (data['result'] == 'success')
{
$('#recordUserVoice').prop('disabled', true);
}
else
{
Swal.fire(
'{{__('Error')}}',
'{{__('An error occurred')}}',
'error'
);
}
},
error: function (err) {
console.log(err);
}
});
}
function createDownloadLink(blob) {
var url = URL.createObjectURL(blob);
var au = document.createElement('audio');
var li = document.createElement('li');
var link = document.createElement('a');
//name of .wav file to use during upload and download (without extendion)
var filename = new Date().toISOString();
//add controls to the <audio> element
au.controls = true;
au.src = url;
//save to disk link
link.href = url;
link.download = filename+".wav"; //download forces the browser to donwload the file using the filename
link.innerHTML = "Save to disk";
//add the new audio element to li
li.appendChild(au);
//add the filename to the li
li.appendChild(document.createTextNode(filename+".wav "))
//add the save to disk link to li
li.appendChild(link);
//upload link
var upload = document.createElement('a');
upload.href="#";
upload.innerHTML = "Upload";
upload.addEventListener("click", function(event){
var xhr=new XMLHttpRequest();
xhr.onload=function(e) {
if(this.readyState === 4) {
console.log("Server returned: ",e.target.responseText);
}
};
var fd=new FormData();
fd.append("audio_data",blob, filename);
xhr.open("POST","upload.php",true);
xhr.send(fd);
})
li.appendChild(document.createTextNode (" "))//add a space in between
li.appendChild(upload)//add the upload link to li
//add the li element to the ol
recordingsList.appendChild(li);
}
document.getElementById('timer').innerHTML =
'00' + ":" + '00';
function startRecord()
{
startRecording();
startTimer();
}
function startTimer() {
$('#recordTextHolder').addClass('d-none');
$('#timer').removeClass('d-none');
var presentTime = document.getElementById('timer').innerHTML;
var timeArray = presentTime.split(/[:]+/);
var m = timeArray[0];
console.log(timeArray[1])
var s = checkSecond((parseInt(timeArray[1]) + 1));
if(parseInt(s) == 5)
{
m = '0'+(parseInt(m)+1)
s = '00'
}
if(m == 2 && s == 1){
stopRecording()
shake()
return
}
document.getElementById('timer').innerHTML =
m + ":" + s;
console.log(m)
setTimeout(startTimer, 1000);
}
function checkSecond(sec) {
if (sec < 10 && sec >= 0) {sec = "0" + sec}; // add zero in front of numbers <10
if (sec < 0) {sec = "59"};
return sec;
</script>
如果有人指导我处理这个问题,我将不胜感激。
您似乎在此处设置 rec
的值:
rec = new Recorder(input,{numChannels:1});
错误消息大概来自这里:
function stopRecording() {
//tell the recorder to stop the recording
rec.stop();
你可以尝试添加一个 console.log 吗?
function stopRecording() {
console.log("rec:", rec)
rec.stop();
报告当时 rec
包含的内容。
感谢您报告说“未定义”。
现在问问自己:'rec' 怎么可能在那个时候是未定义的?
我假设您的控制台正在显示“recordButton clicked”?
还有“getUserMedia() 成功...”?
“录制开始”消息怎么样?
我建议删除以下块:
.catch(function(err) {
});
该块所做的是默默地“吞下”您原本会看到的任何错误消息。一般来说,除非您真的不想知道那里发生的错误,否则不要放入空的 catch 块。
我正在使用 recordJs 库来录制客户端的语音并将其发送到服务器。在firefox等浏览器中运行良好,无任何错误。当我在 chrome 中尝试 运行 它时,它开始录制语音,但是当它调用 stopRecording 函数时,它面临以下错误:
Uncaught TypeError: Cannot read property 'stop' of undefined
at stopRecording (توانایی-پرسش-سن-از-افراد:1209)
at startTimer (توانایی-پرسش-سن-از-افراد:1364)
这是我的 JS 代码:
<script type="text/javascript">
'use strict';
//webkitURL is deprecated but nevertheless
URL = window.URL || window.webkitURL;
let gumStream; //stream from getUserMedia()
let rec; //Recorder.js object
let input; //MediaStreamAudioSourceNode we'll be recording
// shim for AudioContext when it's not avb.
let AudioContext = window.AudioContext || window.webkitAudioContext;
let audioContext //audio context to help us record
function startRecording() {
console.log("recordButton clicked");
/*
Simple constraints object, for more advanced audio features see
https://addpipe.com/blog/audio-constraints-getusermedia/
*/
var constraints = { audio: true, video:false }
/*
Disable the record button until we get a success or fail from getUserMedia()
*/
/*
We're using the standard promise based getUserMedia()
https://developer.mozilla.org/en-US/docs/Web/API/MediaDevices/getUserMedia
*/
navigator.mediaDevices.getUserMedia(constraints).then(function(stream) {
console.log("getUserMedia() success, stream created, initializing Recorder.js ...");
/*
create an audio context after getUserMedia is called
sampleRate might change after getUserMedia is called, like it does on macOS when recording through AirPods
the sampleRate defaults to the one set in your OS for your playback device
*/
audioContext = new AudioContext();
//update the format
// document.getElementById("formats").innerHTML="Format: 1 channel pcm @ "+audioContext.sampleRate/1000+"kHz"
/* assign to gumStream for later use */
gumStream = stream;
/* use the stream */
input = audioContext.createMediaStreamSource(stream);
/*
Create the Recorder object and configure to record mono sound (1 channel)
Recording 2 channels will double the file size
*/
rec = new Recorder(input,{numChannels:1});
//start the recording process
rec.record();
console.log("Recording started");
}).catch(function(err) {
});
}
function pauseRecording(){
console.log("pauseButton clicked rec.recording=",rec.recording );
if (rec.recording){
//pause
rec.stop();
}else{
rec.record();
}
}
function stopRecording() {
//tell the recorder to stop the recording
rec.stop();
//stop microphone access
gumStream.getAudioTracks()[0].stop();
//create the wav blob and pass it on to createDownloadLink
rec.exportWAV(setUserVoice);
}
function setUserVoice(blob)
{
let formData = new FormData
formData.append('userVoice', blob)
$.ajax({
type: 'POST',
headers: {'X-CSRF-TOKEN': $('meta[name="csrf-token"]').attr('content')},
url: '{{ route('user.mockTest.participation.saveUserVoice') }}',
data: formData,
processData: false,
contentType: false,
success: function (data) {
if (data['result'] == 'success')
{
$('#recordUserVoice').prop('disabled', true);
}
else
{
Swal.fire(
'{{__('Error')}}',
'{{__('An error occurred')}}',
'error'
);
}
},
error: function (err) {
console.log(err);
}
});
}
function createDownloadLink(blob) {
var url = URL.createObjectURL(blob);
var au = document.createElement('audio');
var li = document.createElement('li');
var link = document.createElement('a');
//name of .wav file to use during upload and download (without extendion)
var filename = new Date().toISOString();
//add controls to the <audio> element
au.controls = true;
au.src = url;
//save to disk link
link.href = url;
link.download = filename+".wav"; //download forces the browser to donwload the file using the filename
link.innerHTML = "Save to disk";
//add the new audio element to li
li.appendChild(au);
//add the filename to the li
li.appendChild(document.createTextNode(filename+".wav "))
//add the save to disk link to li
li.appendChild(link);
//upload link
var upload = document.createElement('a');
upload.href="#";
upload.innerHTML = "Upload";
upload.addEventListener("click", function(event){
var xhr=new XMLHttpRequest();
xhr.onload=function(e) {
if(this.readyState === 4) {
console.log("Server returned: ",e.target.responseText);
}
};
var fd=new FormData();
fd.append("audio_data",blob, filename);
xhr.open("POST","upload.php",true);
xhr.send(fd);
})
li.appendChild(document.createTextNode (" "))//add a space in between
li.appendChild(upload)//add the upload link to li
//add the li element to the ol
recordingsList.appendChild(li);
}
document.getElementById('timer').innerHTML =
'00' + ":" + '00';
function startRecord()
{
startRecording();
startTimer();
}
function startTimer() {
$('#recordTextHolder').addClass('d-none');
$('#timer').removeClass('d-none');
var presentTime = document.getElementById('timer').innerHTML;
var timeArray = presentTime.split(/[:]+/);
var m = timeArray[0];
console.log(timeArray[1])
var s = checkSecond((parseInt(timeArray[1]) + 1));
if(parseInt(s) == 5)
{
m = '0'+(parseInt(m)+1)
s = '00'
}
if(m == 2 && s == 1){
stopRecording()
shake()
return
}
document.getElementById('timer').innerHTML =
m + ":" + s;
console.log(m)
setTimeout(startTimer, 1000);
}
function checkSecond(sec) {
if (sec < 10 && sec >= 0) {sec = "0" + sec}; // add zero in front of numbers <10
if (sec < 0) {sec = "59"};
return sec;
</script>
如果有人指导我处理这个问题,我将不胜感激。
您似乎在此处设置 rec
的值:
rec = new Recorder(input,{numChannels:1});
错误消息大概来自这里:
function stopRecording() {
//tell the recorder to stop the recording
rec.stop();
你可以尝试添加一个 console.log 吗?
function stopRecording() {
console.log("rec:", rec)
rec.stop();
报告当时 rec
包含的内容。
感谢您报告说“未定义”。
现在问问自己:'rec' 怎么可能在那个时候是未定义的?
我假设您的控制台正在显示“recordButton clicked”?
还有“getUserMedia() 成功...”?
“录制开始”消息怎么样?
我建议删除以下块:
.catch(function(err) {
});
该块所做的是默默地“吞下”您原本会看到的任何错误消息。一般来说,除非您真的不想知道那里发生的错误,否则不要放入空的 catch 块。