使用ffmpeg转换HTML5捕获的录音

时间:2014-07-08 08:33:54

标签: javascript ffmpeg html5-audio

我正在使用可视化工具构建HTML5录音软件。我希望用户在录制语音时,在将文件作为波形上传到blob(服务器端)后,用户应该能够选择使用ffmpeg的该文件的音频格式。到目前为止我所取得的成就是将文件上传为wave。我仍然想做的是:

  • 在服务器上
  • 选择您喜欢的网络编程框架
  • Web编程框架接受上载并将文件存储在服务器上
  • Web编程框架运行ffmpeg(命令行)来处理文件
  • 用户可以下载已处理的文件

到目前为止,这是我的代码:

// 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));
    }
}

0 个答案:

没有答案