转码和流音频 - 如何发送内容范围头 [英] Transcoding and streaming audio - how to send content-range headers

查看:209
本文介绍了转码和流音频 - 如何发送内容范围头的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

快速版本:如何发送正确的内容范围头时,不知道身体长度

Quick version: how to send correct Content-Range headers when don't know the body length?

我有一个FLAC文件。我想跨code它的MP3并立即传输到用户。
我有这样的事情至今:

I have a FLAC file. I want to transcode it to MP3 and stream it to the user immediately. I have something like this so far:

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

这如预期运作,但它的流媒体,所以我不能跳过左右。
显然,我需要做的内容范围的东西。
使用: https://github.com/visionmedia/node-range-parser

This works as intended, but it's "streaming", so I can't skip around. Apparently I need to do Content-Range stuff. Using: 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)
})

这就是我卡住了。
由于我不是等到整个首歌是连接codeD,
我不知道这首歌的大小。
由于我刚刚得到在Chrome中,取消
我假设的内容范围头是没有大小的格式不正确。

This is where I'm stuck. Since I'm not waiting until the entire song is encoded, I don't know the size of the song. Since I just get a "canceled" in Chrome, I'm assuming that the Content-Range header is malformed without the size.

此外,我目前刚刚开放的歌曲在我的浏览器,所以我想它使用了&LT;音频方式&gt; 元素

Also, I'm current just opening the song in my browser, so I assume it uses the <audio> element.

建议?

推荐答案

是的,你的内容范围头是没有大小的格式不正确。然而,你的可能的尝试发送电流的大小你的服务器已经转codeD。虽然我怀疑,铬会优雅地处理不断变化的大小...

Yes, your Content-Range header is malformed without the size. However, you could attempt to send the current size your server had already transcoded. Although I'm doubtful that Chrome would handle the changing size gracefully…

有一些事情你不处理


  1. 您似乎没有被发送 206部分内容 状态(也许这是由库处理,不知道)。

  2. 它看起来并不像你连检查范围请求的最后一部分。 Chrome不正常发送任何东西,但 0 - ,但其他浏览器会。事实上,有些人可能会(在屁股皇家疼痛支持)在单个请求发送多个范围。

  3. 您不是在发送正确的内容范围响应头,你也不能包括你发送的内容结束索引。它应该是这样的:结果
    内容范围:字节0-2048 / 3980841

  4. 最后,如果客户端发出请求的范围是出界,也就是说,没有值范围重叠的资源的服务范围应与的 416请求范围无法满足 状态。

  1. You don't appear to be sending the 206 Partial Content status (maybe this is handled by the library, not sure).
  2. It doesn't look like you're even checking the end part of the range request. Chrome doesn't normally send anything but 0-, but other browsers will. In fact, some might send multiple ranges in a single request (royal pain in the ass to support).
  3. You're not sending a proper Content-Range response header as you are also failing to include the end index of the content you're sending. It should look like this:
    Content-Range: bytes 0-2048/3980841
  4. Finally if the client makes a range request that is out of bounds—that is, none of the range values overlap the extent of the resource—the service should respond with a 416 Requested Range Not Satisfiable status.

编辑:我没有测试过这种特殊情况下,但如果你是从FLAC转码到192kbps的MP3 CBR,我会想象有只限制设置的,将发生的,如果你准备(小于1000位关闭)进行发送的的不准确的内容长度:

I haven't tested this particular case, but if you were transcoding from FLAC to a 192kbps CBR MP3, I would imagine there are only a limit set of possibilities that would occur if you were sending a slightly inaccurate content-length (off by less than a 1000 bits):


  • 音频的最后会得到在由玩家最终剪去。 〜1000位将剪辑约 5毫秒音频(不是显而易见的人)的。

  • 浏览器会忽略的结束索引或内容长度,只是不断接受和/或请求以外的范围内的内容范围您最初,直至关闭回应连接或发送416状态。

  • 音频的丢失/错误的结束可能导致&LT;音频&GT; 抛出一个 MEDIA_ERR_NETWORK MEDIA_ERR_DE code 错误你只需优雅地处理。 (音频仍然在这种情况下被裁剪。)

  • The very end of the audio would get clipped off at the end by the player. ~1000 bits would clip approximately 5ms of audio (not obvious to a human).
  • The browser would ignore the end index or content-length and simply keep accepting and/or requesting ranges outside of the Content-Range you responded with originally until you close the connection or send the 416 status.
  • The missing/erroneous end of the audio may cause the <audio> to throw a MEDIA_ERR_NETWORK or a MEDIA_ERR_DECODE error that you'd simply have to handle gracefully. (The audio would still be clipped in this case.)

这篇关于转码和流音频 - 如何发送内容范围头的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆