GCS二进制文件上传-下载时无法播放音频文件

时间:2019-08-08 19:39:02

标签: google-cloud-storage ogg node-streams

此代码使用opus编码流作为云语音识别的输入(选项:contentType:'OGG_OPUS',sampleRateHertz:48000,),并且工作正常。

但是,示例二进制二进制upload code之后发送到Cloud Storage api的同一流的bufferCopy会导致错误,导致下载后音频无法播放。同样在下载时,使用'ogg'和'opus'文件类型,ffprobe将无法正确检测编码。

控制台和从上载到GCS的输出看起来都不错-有关正确大小的二进制文件在那里,可以使用gsutils下载。

适用于Google云识别api的opus流不适用于云存储api,因为它是音频流​​的简单文件接收器。我使用gsutil从云中获取音频文件,但是它无法在任何播放器中播放,并且ffprobe不会检测到编码。

我不知道如何调试问题。客户端上的原始音频Blob可以正常播放,其字节大小非常接近,但不等于上传到GCS api /从GCS api下载的文件的大小。

下面的代码详细信息:socket-io用于从js层获取数据到此Express服务器实例。...

  client.on('startGoogleCloudStream', function (data) {
    // startRecognitionStream(this, data);
    console.log('STRMbeg ' + typeof recognizeStream);
    rs = new stream.Readable();
    rs._read = function () {};
    readStream1 = new ReadableStreamClone(rs);
    readStream2 = new ReadableStreamClone(rs);
    startRecognitionStream(this);

    let rfil = 'audio/' +uuidv4() + '.ogg'; //typ '.opus' same error
    const file = myBucket.file(rfil);
    var otstrm = file.createWriteStream({
      metadata: {
        contentType: 'audio/ogg'
      },
      gzip: false,
      resumable: false
    });
    readStream1.pipe(recognizeStream);// works fine
    readStream2.pipe(otstrm) // gets a corrupted binary up on cloud
    .on('error', function(err) {
      console.log('second strm ' + err);
    })
    .on('finish', function() {
      console.log('Done BcketFilaudio local');
    });
  });

  client.on('endGoogleCloudStream', function (data) {
    console.log('STRMend');
    // stopRecognitionStream();
    rs.push(null); // null is Stream.END
    recognizeStream = null;
  });

  client.on('binaryData', function (data) {
    console.log('data ' + data.length ); // log binary data
    if (recognizeStream !== null) {
      let _bfr = Buffer.from(data.buffer);
      rs.push(_bfr);
    }
  });

  function startRecognitionStream (client, data) {
    recognizeStream = speechClient.streamingRecognize(request)
      .on('error', console.error)
      .on('data', (data) => { // back to client on socket.io
      //  Dev only logging
        process.stdout.write(
          (data.results[0] && data.results[0].alternatives[0])
          ? `Transcription: ${data.results[0].alternatives[0].transcript}\n`
          : `\n\nReached transcription time limit, press Ctrl+C\n`
        );

        client.emit('speechData', data);
        if (data.results[0] && data.results[0].isFinal) {
          postRecSpeech(data.results[0].alternatives[0].transcript);
        }
      });
  }

1 个答案:

答案 0 :(得分:1)

由于某些原因,GCS不接受使用Cloud Speech的流的副本,并且由于向多个API的输入而无法重用服务器端流。

-解决方法

即使流(音频记录器)已经作为流在服务器端使用,流流块也必须浓缩到客户端上的Blob,然后重新发布以像执行curl / POST一样表达...

curl -X POST  --header "Transfer-Encoding: chunked" --header "Content-Type: audio/ogg; rate=48000"  --data-binary @myaudio.opus "https://localhost${PORT}/audio/upload"

基于this code

下面的我的快速代码可以正常工作,而GCS音频可以很好地进行下载。

app.post("/audio/upload", gcsAudio);

const gcsAudio = (req, res) => {
  const type = req.get('Content-Type');
  let gcsname = 'audio/' +uuidv4() + '.opus';
  const files = myBucket.file(gcsname);
  const stream = files.createWriteStream({
    metadata: {
      contentType: type
    },
    resumable: false
  });

 req
   .pipe(stream)
   .on("error", (err) => {
     restify.InternalServerError(err);
   })
   .on('finish', () => {
     res.json({
      success: true,
      fileUrl: `https://storage.googleapis.com/${_bucket}/${gcsname}`
    })
   });
};