繁体   English   中英

使用 sip.js 录制来自 SIP 呼叫的麦克风和音频

[英]Record mic and audio from SIP call using sip.js

晚上好堆栈溢出! 我真的需要我的一个项目的帮助,我正在使用 sip.js 和 VoIP 对电话号码进行真正的呼叫。

目标

我希望允许用户录制音频和麦克风并将数据保存在服务器上(以 base64 编码或作为文件)。 所以我在谈话之后可以再次听到谈话并将其用于我的目的(员工培训)。

问题

我听不到说话人的声音,这是通过 -HTML 标记(使用 sip.js 插件)发出的。 到目前为止,我还没有找到任何方法可以通过此音频标签成功保存声音流。

到目前为止我所做的

我已经成功地找到了如何使用名为AudioRecorder的插件录制麦克风的音频,该插件允许我通过麦克风录制音频并保存。 我稍微改变了代码,所以它被保存为 base64 编码。 这一切都按预期进行,尽管我只能听到我自己的声音,而不是与我交谈的人的声音。

因为我成功录制了自己的声音,所以我查看了 AudioRecorder 插件并尝试反转插件以从音频标签录制。 我在 AudioRecorder 中找到了“createMediaStreamSource”函数,我想使用它不起作用的 -tag(正如我怀疑的那样,因为它本身中的 -tag 不是流(我理解)。

守则

我基本上是使用 sip.js 插件通过使用以下代码建立对电话号码的呼叫(仅使用示例,匹配我的代码,因为我的原始代码包含一些不需要在此处显示的附加值) :

// Create a user agent called bob, connect, and register to receive invitations.
var userAgent = new SIP.UA({
  uri: 'bob@example.com',
  wsServers: ['wss://sip-ws.example.com'],
  register: true
});
var options = { media: { constraints: { audio: true, video: false }, render: { remote: document.getElementById("audio") } } };

然后我使用内置的邀请功能拨打电话号码,剩下的就交给电话号码了。 音频和麦克风现已启动并运行。

userAgent.invite("+4512345678", options);

我现在可以和我最好的新朋友鲍勃交谈了。 但是现在除了我自己的声音我不能录制。

下一步是什么?

我真的很想了解如何录制“鲍勃”的声音并将其存储在与我自己的声音相同的文件中。 如果我必须录制两个单独的文件并同步播放它们,我不会介意,但如果愿意的话。

我知道这可能只是寻求帮助,而没有显示我自己尝试做的任何真实代码,但我不得不承认我只是摆弄了几个小时的代码没有任何好的结果,现在我在尖叫帮助。

预先感谢大家,并对语法错误和(错误)使用语言表示抱歉。

好的,所以我终于找到了解决问题的方法,尽管我想在这里分享。

我为解决这个问题所做的是在麦克风的“正常”录音脚本中添加一行简单的代码。 录制麦克风音频的脚本是:

window.AudioContext = window.AudioContext || window.webkitAudioContext;

var audioGlobalContext = new AudioContext();
var audioOutputAnalyser
var inputPoint = null,
    audioRecorder = null;
var recording = false;

// Controls the start and stop of recording
function toggleRecording( e ) {
    if (recording == true) {
        recording = false;
        audioRecorder.stop();
        audioRecorder.getBuffers( gotBuffers );
        console.log("Stop recording");
    } else {
        if (!audioRecorder)
            return;
        recording = true;
        audioRecorder.clear();
        audioRecorder.record();
        console.log("Start recording");
    }
}

function gotBuffers(buffers) {
    audioRecorder.exportWAV(doneEncoding);
}

function doneEncoding(blob) {
    document.getElementById("outputAudio").pause();
    Recorder.setupDownload(blob);
}

function gotAudioMicrophoneStream(stream) {
    var source = audioGlobalContext.createMediaStreamSource(stream);
    source.connect(inputPoint);
}

function initAudio() {
        if (!navigator.getUserMedia)
            navigator.getUserMedia = navigator.webkitGetUserMedia || navigator.mozGetUserMedia;
        if (!navigator.cancelAnimationFrame)
            navigator.cancelAnimationFrame = navigator.webkitCancelAnimationFrame || navigator.mozCancelAnimationFrame;
        if (!navigator.requestAnimationFrame)
            navigator.requestAnimationFrame = navigator.webkitRequestAnimationFrame || navigator.mozRequestAnimationFrame;

    inputPoint = audioGlobalContext.createGain();

    navigator.getUserMedia({
        "audio": {
            "mandatory": {
                "googEchoCancellation": "true",
                "googAutoGainControl": "false",
                "googNoiseSuppression": "true",
                "googHighpassFilter": "false"
            },
            "optional": []
        },
    }, gotAudioMicrophoneStream, function(e) {
        alert('Error recording microphone');
        console.log(e);
    });

    var analyserNode = audioGlobalContext.createAnalyser();
    analyserNode.fftSize = 2048;
    inputPoint.connect(analyserNode);
    var zeroGain = audioGlobalContext.createGain();
    zeroGain.gain.value = 0.0;
    inputPoint.connect(zeroGain);
    zeroGain.connect(audioGlobalContext.destination);

    audioRecorder = new Recorder(inputPoint);
}

window.addEventListener('load', initAudio );

我正在寻找将音频标签声音转换为音频源的函数是createMediaElementSource()所以我所做的是添加这个函数:

function gotAudioOutputStream() {
    var source = audioGlobalContext.createMediaElementSource(document.getElementById("outputAudio"));
    source.connect(inputPoint);
    source.connect(audioGlobalContext.destination);
}

并且在 navigator.getUserMedia 之后的 initAudio() 函数中添加了对该函数的调用。 完成的代码(带有 HTML)看起来像这样

window.AudioContext = window.AudioContext || window.webkitAudioContext;

var audioGlobalContext = new AudioContext();
var audioOutputAnalyser
var inputPoint = null,
    audioRecorder = null;
var recording = false;

// Controls the start and stop of recording
function toggleRecording( e ) {
    if (recording == true) {
        recording = false;
        audioRecorder.stop();
        audioRecorder.getBuffers( gotBuffers );
        console.log("Stop recording");
    } else {
        if (!audioRecorder)
            return;
        recording = true;
        audioRecorder.clear();
        audioRecorder.record();
        console.log("Start recording");
    }
}

function gotBuffers(buffers) {
    audioRecorder.exportWAV(doneEncoding);
}

function doneEncoding(blob) {
    document.getElementById("outputAudio").pause();
    Recorder.setupDownload(blob);
}

function gotAudioMicrophoneStream(stream) {
    var source = audioGlobalContext.createMediaStreamSource(stream);
    source.connect(inputPoint);
}

function gotAudioOutputStream() {
    var source = audioGlobalContext.createMediaElementSource(document.getElementById("outputAudio"));
    source.connect(inputPoint);
    source.connect(audioGlobalContext.destination);
}

function initAudio() {
        if (!navigator.getUserMedia)
            navigator.getUserMedia = navigator.webkitGetUserMedia || navigator.mozGetUserMedia;
        if (!navigator.cancelAnimationFrame)
            navigator.cancelAnimationFrame = navigator.webkitCancelAnimationFrame || navigator.mozCancelAnimationFrame;
        if (!navigator.requestAnimationFrame)
            navigator.requestAnimationFrame = navigator.webkitRequestAnimationFrame || navigator.mozRequestAnimationFrame;

    inputPoint = audioGlobalContext.createGain();

    navigator.getUserMedia({
        "audio": {
            "mandatory": {
                "googEchoCancellation": "true",
                "googAutoGainControl": "false",
                "googNoiseSuppression": "true",
                "googHighpassFilter": "false"
            },
            "optional": []
        },
    }, gotAudioMicrophoneStream, function(e) {
        alert('Error recording microphone');
        console.log(e);
    });

    gotAudioOutputStream();

    var analyserNode = audioGlobalContext.createAnalyser();
    analyserNode.fftSize = 2048;
    inputPoint.connect(analyserNode);
    var zeroGain = audioGlobalContext.createGain();
    zeroGain.gain.value = 0.0;
    inputPoint.connect(zeroGain);
    zeroGain.connect(audioGlobalContext.destination);

    audioRecorder = new Recorder(inputPoint);
}

window.addEventListener('load', initAudio );

<!doctype html>
<html>
<head>
    <meta name="viewport" content="width=device-width,initial-scale=1">
    <title>Audio Recorder</title>
    <script src="assets/js/AudioRecorder/js/recorderjs/recorder.js"></script>
    <script src="assets/js/AudioRecorder/js/main.js"></script>
</head>
<body>
    <audio id="outputAudio" autoplay="true" src="test.mp3" type="audio/mpeg"></audio>
    <audio id="playBack"></audio>
    <div id="controls">
        <img id="record" src="assets/js/AudioRecorder/img/mic128.png" onclick="toggleRecording(this);">
    </div>
</body>
</html>

这会记录您的声音和来自音频元素标签的声音。 简单。 希望所有与我有相同问题的人都可以“倒带”音频 API,这会有所帮助。

上面显示的代码片段需要 Recorder.js 才能工作。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM