在 Chrome 浏览器中使用 recordJs 库期间将定义的变量转换为未定义

Posted

技术标签:

【中文标题】在 Chrome 浏览器中使用 recordJs 库期间将定义的变量转换为未定义【英文标题】:converting defined variable as undefined during using recordJs library in chrome browser 【发布时间】:2021-09-27 08:12:43 【问题描述】:

我正在使用 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>

如果有人指导我处理这个问题,我将不胜感激。

【问题讨论】:

【参考方案1】:

您似乎在此处设置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 块。

【讨论】:

您好,先生,感谢您的热情回复。我试过了,它重新运行“未定义” 非常感谢,我已将 console.log(error) 放在 catch 块中,并找出了确切的问题。感谢您的青睐。 太棒了!能否请您将答案标记为“已接受”?

以上是关于在 Chrome 浏览器中使用 recordJs 库期间将定义的变量转换为未定义的主要内容,如果未能解决你的问题,请参考以下文章

通过 HTML5 API(RecordJS 或替代方法)将音频录制到 AAC

在程序中怎么调用chrome浏览器

使用 Chrome 扩展程序在 Google Chrome 浏览器中访问搜索查询文本

Chrome 浏览器无法使用 Java 在 Appium 中启动

如何设置默认使用chrome内核

在Chrome 中使用Vimium