4

クイック バージョン:Content-Range本文の長さが分からない場合に正しいヘッダーを送信する方法は?

FLACファイルがあります。それを MP3 にトランスコードして、すぐにユーザーにストリーミングしたいと考えています。これまでのところ、次のようなものがあります。

function transcode(file) {
  var spawn = require('child_process').spawn

  var decode = spawn('flac', [
    '--decode',
    '--stdout',
    file
  ])

  var encode = spawn('lame', [
    '-V0',
    '-',
    '-'
  ])

  decode.stdout.pipe(encode.stdin)

  return encode
}

var express = require('express')
var app = express()

app.get('/somefile.mp3', function (req, res) {
  res.setHeader('Accept-Ranges', 'bytes')
  res.setHeader('Content-Range', 'bytes')
  res.setHeader('Content-Type', 'audio/mpeg')
  transcode(file).stdout.pipe(res)
})

これは意図したとおりに機能しますが、「ストリーミング」であるため、スキップできません。どうやら私は何かをする必要があるようContent-Rangeです。使用: https://github.com/visionmedia/node-range-parser

function sliceStream(start, writeStream, readStream) {
  var length = 0
  var passed = false

  readStream.on('data', function (buf) {
    if (passed) return writeStream.write(buf);

    length += buf.length

    if (length < start) return;

    passed = true
    writeStream.write(buf.slice(length - start))
  })

  readStream.on('end', function () {
    writeStream.end()
  })
}

var parseRange = require('range-parser')

app.get('/somefile.mp3', function (req, res) {
  var ranges = parseRange(Infinity, req.headers['range'])

  if (ranges === -1 || ranges === -2) return res.send(400);

  var start = ranges[0].start

  res.setHeader('Accept-Ranges', 'bytes')
  res.setHeader('Content-Type', 'audio/mpeg')

  if (!start) {
    res.setHeader('Content-Range', 'bytes')
    transcode(file).stdout.pipe(res)
    return
  }

  res.setHeader('Content-Range', 'bytes ' + start + '-')
  sliceStream(start, transcode(file).stdout, res)
})

これは私が立ち往生しているところです。曲全体がエンコードされるまで待っていないので、曲のサイズはわかりません。Chromeで「キャンセル」されたばかりなので、Content-Rangeヘッダーの形式が正しくないと想定しています。

また、現在ブラウザで曲を開いているだけなので、<audio>要素を使用していると思います。

提案?

4

1 に答える 1

6

はい、Content-Rangeヘッダーの形式が正しくありません。サイズがありません。ただし、サーバーが既にトランスコードした現在のサイズを送信することはできます。Chrome がサイズの変更を適切に処理するかどうかは疑問ですが…</p>

あなたが扱っていないものがいくつかあります

  1. ステータスを送信していないようです206 Partial Content(これはライブラリによって処理される可能性がありますが、わかりません)。
  2. 範囲リクエストの最後の部分をチェックしているようにも見えません。Chrome は通常、 以外は送信しませんが0-、他のブラウザは送信します。実際、1 回のリクエストで複数の範囲を送信する場合もあります (お尻の王室の痛み)。
  3. Content-Range送信しているコンテンツの終了インデックスも含めていないため、適切な応答ヘッダーを送信していません。次のようになります。
    Content-Range: bytes 0-2048/3980841
  4. 最後に、クライアントが範囲外の範囲要求を行う場合 (つまり、どの範囲値もリソースの範囲と重複しない場合)、サービスは416 Requested Range Not Satisfiableステータスで応答する必要があります。

編集:この特定のケースはテストしていませんが、FLAC から 192kbps CBR MP3 にトランスコードする場合、わずかに不正確なコンテンツ長 (off 1000 ビット未満):

  • オーディオの最後は、プレーヤーによって最後に切り取られます。~1000 ビットで約5 ミリ秒のオーディオがクリップされます(人間にはわかりません)。
  • Content-Rangeブラウザーは終了インデックスまたはコンテンツの長さを無視し、接続を閉じるか 416 ステータスを送信するまで、最初に応答した範囲外の範囲を単に受け入れおよび/または要求し続けます。
  • 音声の終わりが見つからないか誤っている<audio>と、MEDIA_ERR_NETWORKまたはMEDIA_ERR_DECODEエラーが発生する可能性がありますが、適切に処理する必要があります。(この場合、オーディオはまだクリップされます。)
于 2013-01-13T18:13:12.993 に答える