node.js - Icecast:我有奇怪的行为,重复轨道结束,以及我的 Icecast 服务器的音高变化

标签 node.js networking audio server icecast

我几天前才开始使用icecast,所以如果我在某个地方塞了什么东西,请告诉我。
我对icecast有一个奇怪的问题。每次在icecast上“完成”一首轨道时,当前播放轨道的结尾部分(我认为轨道的64kbs)在下一首歌曲播放之前重复大约2到3次,但下一首歌曲没有开始播放在开始时,但经过几秒钟。此外,我注意到播放速度(以及音高)有时也与原始速度不同。
我咨询了this postthis post that was quoted below这教会了我<burst-on-connect><burst-size>标签用于。它也教会了我这个:

What's happening here is that nothing is being added to the buffer, so clients connect, get the contents of that buffer, and then the stream ends. The client must be re-connecting repeatedly, and it keeps getting that same buffer.


为布拉德的那篇文章干杯。该帖子的评论部分提供了此问题的解决方案,并表示减少 <source-timeout> icecast 服务器,以便它更快地关闭连接并停止任何重复。但这是假设我想关闭挂载点,但我不这样做,因为我使用 Icecast 实际上是一个 24/7 广播播放器。如果我确实关闭了我的挂载点,那么会发生什么是 VLC 只是关闭并且不再重复尝试连接。除非这是错误的。我不知道。
我使用 VLC 来收听 Icecast 流的播放,我使用 nodeshout这是一组为 node.js 构建的 libshout 绑定(bind)。我使用 nodeshout 将数据发送到我的 icecast 服务器上的一堆坐骑。在 future ,我计划制作一个可以收听 icecast 流的网站,这意味着它将取代 VLC。
icecast.xml
<limits>
        <clients>100</clients>
        <sources>4</sources>
        <queue-size>1008576</queue-size>
        <client-timeout>30</client-timeout>
        <header-timeout>15</header-timeout>
        <source-timeout>30</source-timeout>
        <burst-on-connect>1</burst-on-connect>
         <burst-size>252144</burst-size>
    </limits>
这是我的 node.js 服务器上的音频发送代码的摘要。
Node
// these lines of code is a smaller part of a function, and this sets all the information. The variables name, description etc come from the arguments of the function
    var nodeshout = require("nodeshout");

    let shout = nodeshout.create();
    shout.setHost('localhost');
    shout.setPort(8000);

    shout.setUser('source');
    shout.setPassword(process.env.icecastPassword);  //password in .env file

    shout.setName(name);
    shout.setDescription(description);
    shout.setMount(mount);
    shout.setGenre(genre);

    shout.setFormat(1); // 0=ogg, 1=mp3
    shout.setAudioInfo('bitrate', '128');
    shout.setAudioInfo('samplerate', '44100');
    shout.setAudioInfo('channels', '2');
    return shout



// now meanwhile somewhere lower in the file, there is this summary of how the audio is sent to the icecast server


var nodeshout = require("nodeshout")
var {FileReadStream, ShoutStream} = require("nodeshout") //here is where the FileReadStream and ShoutStream functions come from

const filecontent = new FileReadStream(pathToSong, 65536); //if I change the 65536 to a higher value, then more bytes are being repeated at the end of the track. If I decrease this, it starts sounding buggy and off.  
var streamcontent = filecontent.pipe(new ShoutStream(shoutstream)) 

streamcontent.on('finish', () => {
    next()
    console.log("Track has finished on " + stream.name + ": " + chosenTrack)
})
我还注意到更奇怪的行为。在上一首歌曲的最后一个 block 重复了几次之后,这就是服务器调用 streamcontent.on('finish') 的时候。位于 nodejs 脚本中的事件,然后它才警告我轨道已完成。
我尝试过的
我试着弄乱 <source-timeout>标签,在nodejs上发送的字节数(或我不确定的位),突发大小,我也尝试完全关闭突发,但它会导致 super 奇怪的行为。
我还认为每次为每首歌曲创建一个新流是一个坏主意,如 new ShoutStream(shoutstream) 所示。当管道传输文件数据时,但使用相同的流意味着程序将返回错误,因为它会在它说它已经关闭后将下一个轨道写入到喊流。
如果需要更多信息来弄清楚发生了什么,我可以提供。谢谢你的时间。
编辑:我想补充一下:你认为我应该手动控制发送到 icecast 的字节数,然后使用相同的流对象而不是每次都调用一个新对象吗?

最佳答案

我发现了为什么流没有播放某些轨道而不是其他轨道。
我是如何到达那里的
我无法为我的流切换到 ogg/vorbis 或 ogg/opus,所以我不得不对我的源客户端做一些事情。我仔细检查了一切是否正确,并且我的音频文件的比特率正确。当我使用 ffprobe audio.mp3 运行 ffprobe 工具时有时比特率不符合 120kbps、128kbps、192、312 等的典型速率。它总是一些奇怪的值,例如 129852 只是为了提供一个例子。
然后我下载了 checkmate mp3 检查器 here并检查了我的音频文件,它们都以可变比特率编码!!! VBR该死!
TLDR
我通过使用 ffmpeg 将所有轨道重新编码为 128kbps 的恒定比特率来解决我的问题。
快速编辑:我很确定诸如 Darkice 之类的程序可能已经支持到 Icecast 服务器的可变比特率传输,但对我来说使用 darkice 是不切实际的,因此我坚持使用 nodeshout。

关于node.js - Icecast:我有奇怪的行为,重复轨道结束,以及我的 Icecast 服务器的音高变化,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/63027707/

相关文章:

javascript - 使用sequelize,是否可以与同一对象的多个实例建立关联

c++ - WinSock accept() 返回 204.204.204.204

.net - 使用 Visual Basic 扫描 Wifi 网络

audio - ffmpeg:连接视频和音频文件

java - 在 MVC Java 游戏中将声音放在哪里?

visual-studio-2010 - 无法让OpenAL播放声音

node.js - OffSet + Limit 查询使用 adonis/node.js 返回错误结果

node.js - 运行 Electron 时出错

javascript - 在 Promise 返回函数中找到第一个成功

java - 在 Java 中组合 UDP 和 RPC 的最简单和最有效的方法是什么?