【问题标题】:Recording voice using HTML5 and processing it with ffmpeg使用 HTML5 录制语音并使用 ffmpeg 处理
【发布时间】:2014-08-28 20:18:04
【问题描述】:

我需要在我的 javascript/HTML5 项目中使用 ffmpeg,它允许用户选择他想要打开音频的格式。我对 ffmpeg 一无所知,我一直在做很多研究我不知道不知道如何在我的项目中使用它。我找到了一个示例https://github.com/sopel39/audioconverter.js,但问题是如何安装 8 mg to m 项目的 ffmpeg.js。如果有人可以帮助我,我将非常感激 这是我的完整代码:

javascript 页面:

// variables
var leftchannel = [];
var rightchannel = [];
var recorder = null;
var recording = false;
var recordingLength = 0;
var volume = null;
var audioInput = null;
var sampleRate = 44100;
var audioContext = null;
var context = null;
var outputString;



if (!navigator.getUserMedia)
navigator.getUserMedia = navigator.getUserMedia ||
                         navigator.webkitGetUserMedia ||
                         navigator.mozGetUserMedia || 
                         navigator.msGetUserMedia;

if (navigator.getUserMedia){
navigator.getUserMedia({audio:true}, success, function(e) {
alert('Error capturing audio.');
});
} else alert('getUserMedia not supported in this browser.');



function getVal(value)
  {

// if R is pressed, we start recording
if ( value == "record"){
    recording = true;
    // reset the buffers for the new recording
    leftchannel.length = rightchannel.length = 0;
    recordingLength = 0;
    document.getElementById('output').innerHTML="Recording now...";

 // if S is pressed, we stop the recording and package the WAV file
 } else if ( value == "stop" ){

    // we stop recording
    recording = false;
    document.getElementById('output').innerHTML="Building wav file...";

    // we flat the left and right channels down
    var leftBuffer = mergeBuffers ( leftchannel, recordingLength );
    var rightBuffer = mergeBuffers ( rightchannel, recordingLength );
    // we interleave both channels together
    var interleaved = interleave ( leftBuffer, rightBuffer );



    var buffer = new ArrayBuffer(44 + interleaved.length * 2);
    var view = new DataView(buffer);

    // RIFF chunk descriptor
    writeUTFBytes(view, 0, 'RIFF');
    view.setUint32(4, 44 + interleaved.length * 2, true);
    writeUTFBytes(view, 8, 'WAVE');
    // FMT sub-chunk
    writeUTFBytes(view, 12, 'fmt ');
    view.setUint32(16, 16, true);
    view.setUint16(20, 1, true);
    // stereo (2 channels)
    view.setUint16(22, 2, true);
    view.setUint32(24, sampleRate, true);
    view.setUint32(28, sampleRate * 4, true);
    view.setUint16(32, 4, true);
    view.setUint16(34, 16, true);
    // data sub-chunk
    writeUTFBytes(view, 36, 'data');
    view.setUint32(40, interleaved.length * 2, true);


    var lng = interleaved.length;
    var index = 44;
    var volume = 1;
    for (var i = 0; i < lng; i++){
        view.setInt16(index, interleaved[i] * (0x7FFF * volume), true);
        index += 2;
    }

    var blob = new Blob ( [ view ], { type : 'audio/wav' } );

    // let's save it locally

    document.getElementById('output').innerHTML='Handing off the file now...';
    var url = (window.URL || window.webkitURL).createObjectURL(blob);

    var li = document.createElement('li');
    var au = document.createElement('audio');
    var hf = document.createElement('a');

    au.controls = true;
    au.src = url;
    hf.href = url;
    hf.download = 'audio_recording_' + new Date().getTime() + '.wav';
    hf.innerHTML = hf.download;
    li.appendChild(au);
    li.appendChild(hf);
    recordingList.appendChild(li);

}
}


function success(e){

audioContext = window.AudioContext || window.webkitAudioContext;
context = new audioContext();


volume = context.createGain();

// creates an audio node from the microphone incoming stream(source)
source = context.createMediaStreamSource(e);

// connect the stream(source) to the gain node
source.connect(volume);

var bufferSize = 2048;

recorder = context.createScriptProcessor(bufferSize, 2, 2);

//node for the visualizer
analyser = context.createAnalyser();
analyser.smoothingTimeConstant = 0.3;
analyser.fftSize = 512;

splitter = context.createChannelSplitter();
//when recording happens
recorder.onaudioprocess = function(e){

    if (!recording) return;
    var left = e.inputBuffer.getChannelData (0);
    var right = e.inputBuffer.getChannelData (1);

    leftchannel.push (new Float32Array (left));
    rightchannel.push (new Float32Array (right));
    recordingLength += bufferSize;

    // get the average for the first channel
    var array =  new Uint8Array(analyser.frequencyBinCount);
    analyser.getByteFrequencyData(array);

    var c=document.getElementById("myCanvas");
    var ctx = c.getContext("2d");
    // clear the current state
    ctx.clearRect(0, 0, 1000, 325);
    var gradient = ctx.createLinearGradient(0,0,0,300);
    gradient.addColorStop(1,'#000000');
    gradient.addColorStop(0.75,'#ff0000');
    gradient.addColorStop(0.25,'#ffff00');
    gradient.addColorStop(0,'#ffffff');
    // set the fill style
    ctx.fillStyle=gradient;
    drawSpectrum(array);
    function drawSpectrum(array) {
        for ( var i = 0; i < (array.length); i++ ){
                var value = array[i];
                ctx.fillRect(i*5,325-value,3,325);
            } 

    }
}

function getAverageVolume(array) {
    var values = 0;
    var average;

    var length = array.length;

    // get all the frequency amplitudes
    for (var i = 0; i < length; i++) {
        values += array[i];
    }

    average = values / length;
    return average;
}

    // we connect the recorder(node to destination(speakers))
    volume.connect(splitter);
    splitter.connect(analyser, 0, 0);

    analyser.connect(recorder);
    recorder.connect(context.destination);

}




function mergeBuffers(channelBuffer, recordingLength){
var result = new Float32Array(recordingLength);
var offset = 0;
var lng = channelBuffer.length;
for (var i = 0; i < lng; i++){
var buffer = channelBuffer[i];
result.set(buffer, offset);
offset += buffer.length;
}
    return result;
   }

function interleave(leftChannel, rightChannel){
var length = leftChannel.length + rightChannel.length;
var result = new Float32Array(length);

var inputIndex = 0;

for (var index = 0; index < length; ){
 result[index++] = leftChannel[inputIndex];
 result[index++] = rightChannel[inputIndex];
 inputIndex++;
}
return result;
}


function writeUTFBytes(view, offset, string){ 
var lng = string.length;
for (var i = 0; i < lng; i++){

view.setUint8(offset + i, string.charCodeAt(i));
}
}

这里是html代码:

<!DOCTYPE html>
<html>

<head>
    <meta charset="utf-8">
    <meta http-equiv="X-UA-Compatible" content="IE=edge,chrome=1">
    <title>Simple Web Audio Recorder</title>
    <script src="js/functions.js"></script>
   <link href="css/style.css" rel="stylesheet" type="text/css" />
</head>
 <body>
    <input type="button" value="record" onclick="getVal(this.value)">
    <input type="button" value="stop" onclick="getVal(this.value)">
    <p id="output"></p>
<ul id="recordingList"></ul>
<canvas id="myCanvas" width="1000" height="325" style="display: block;"></canvas>

</body>
</html>

【问题讨论】:

    标签: javascript ffmpeg html5-audio


    【解决方案1】:

    ffmpeg 是一个原生库。通过 Emscripten 运行它在日常 Web 开发中可能还不实用。要使用 Emcscripten 和由它生成的 JS,需要一些高级 JavaScript 技能。

    相反,我建议您将音频文件上传到服务器端并在那里进行转换。

    • 将声音录制为 blob using getUserMedia()

    • Upload the recorded blob to the server

    • 在服务器端选择您喜欢的 Web 编程框架

    • Web 编程框架接受上传并将文件存储在服务器上

    • Web 编程框架运行处理文件的 ffmpeg(命令行)

    • 用户可以下载处理后的文件

    这是将上传的 MP3 文件转换为 48kbit AAC 文件的 Python 示例:

    def create_prelisten_aac(mp3, aac):
        """
        Run en-code for a single file
    
        Do 48 kbit files for prelisten.
        """
        cmdline = [ FFMPEG, '-y', '-i', mp3, '-acodec', 'libfaac', '-ar', '22050', '-ac', '1', '-ab', '48000', aac ]
        return subprocess.call(cmdline)
    

    在这里你可以找到这个应用程序的完整源代码:

    https://github.com/miohtama/LibertyMusicStore

    【讨论】:

    • 谢谢你的帮助。但是如果我需要将 ffmpeg.js 添加到我的项目中怎么办?这是一个 8 mb 的文件,我该怎么做?
    • 将文件复制到您的项目文件夹。但是您大多做错了,这听起来像是您组织中的一个社会问题。如果您所做的事情有意义,请与您的队友讨论。
    • 我将编辑我到目前为止所做的代码。我只是不知道在哪里使用 ffmpeg 如果你能帮助我请检查我的代码
    • 这是一个非常具体的问题,您可能需要自己弄清楚。但是,为了获得灵感,您可以查看像 bgrins.github.io/videoconverter.js 这样的项目,它们已经在浏览器中直接使用 ffmpeg
    猜你喜欢
    • 2014-10-06
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2013-01-07
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多