0

我正在用 Java 制作一个直播服务器,但我遇到了麻烦。如果我向客户端 (VLC/WINAMP) 发送 HTTP 响应,我的服务器可以很好地传输数据:

HTTP/1.1 200 OK\r\nContent-Type:audio/mpeg\r\n\r\n\

然后开始流式传输文件,但是,当我向客户端发送 ICY 响应时,声音开始变得有点断断续续和吱吱作响,有时播放速度有点快。有时它会同时播放播放列表中所有歌曲的一小部分,但如果我断开客户端并再次连接,它会正常播放,在这种情况下会有点断断续续和吱吱作响。我试图连接到互联网上的广播服务器,它们看起来完美无瑕。(我还以 24kb 的块发送我的数据)

这是我的 ICY 回复

String respond = "ICY 200 OK\r\n"
                     +"icy-notice1: <BR> This stream requires"
                     + "<a href=\"http://www.videolan.org/\">VLC</a><BR>\r\n"
                     + "icy-notice2: Lee Shoutcast<BR>\r\n"
                     + "icy-name: Lee's Mix\r\n"
                     + "icy-genre: Rock\r\n"
                     + "icy-url: http://localhost:9025\r\n"
                     + "content-type: audio/mpeg\r\n"
                     + "icy-pub: 1\r\n"
                     + "icy-metaint: 24576\r\n"
                     + "icy-br: 96\r\n\r\n";

我做了一点阅读,发现我必须以 Header|DataChunk|Header..... 格式发送客户端数据,所以我查找了如何做标题并想出了这个作为测试跑去看看它是否能弥补波动。

String header = "";

    String heading ="StreamTitle='The year of the ram';"
            + "StreamUrl='someaddress:9025';";

    byte []headingBytes = heading.getBytes();

    int NumberOfBlocks = ((headingBytes.length - 1) / 16) + 1;

    int toPad = NumberOfBlocks*16 - headingBytes.length;


    header =  NumberOfBlocks + "StreamTitle='The year of the ram';"
            + "StreamUrl='http://someaddress:9025';";


    String finalStr = header + padding(toPad);

    System.out.println(finalStr);

    byte []finalByte = finalStr.getBytes();

    return finalByte;

填充方法只是在字符串的右侧添加零:

public String padding(int numberOfPads)
{
    String ret = "";

    for(int i = 1; i <= numberOfPads; i++)
    {
        ret += "0";
    }

    return ret;
}

结果字符串是:

5StreamTitle='The year of the ram';StreamUrl='http://someaddress:9025';000000000000

然后我将字符串转换为字节并将这些标题字节写入流,然后写入我的 24kb 块,然后写入标题等等。这似乎根本没有帮助这种情况。SHOUTcast 有什么我做错了,因为它与 ICEcast 完美配合吗?

PS 我知道代码看起来有点乱,可能会更好,但这只是一个测试。我还发送这个常量字符串作为测试,看看它是否有帮助。计划是正确地做它如果它有效。

任何帮助表示赞赏。

我的信息是从

编辑:

这就是我确定何时发送字节的方式(此代码在 while(true) 循环中)

            buffer = new byte[24576];

            //read the file into the buffer
            bytesRead = song.read(buffer);

            //start streaming the file.
            outputStream.write(buffer);

将 24KB 的歌曲读入缓冲区,然后写入输出流。我删除了编写元数据的代码,但我在 outputStream.write(buffer) 之前编写了元数据。

VLC 和 wimamp 确实发送 icy-metadata = 1。

4

1 回答 1

1

首先,我建议不要模仿 SHOUTcast 的状态行ICY 200 OK。改为使用HTTP/1.0 200 OK。通过这种方式,您将与客户端有更好的兼容性。

现在,正如您所怀疑的,您的服务器表现不同的原因是元数据。响应头控制元块之间的icy-metaint间隔。如果客户端请求,您应该只插入此标头并返回元数据。客户端必须发送icy-metadata: 1请求元数据。否则,您只能发送流数据。

您没有展示如何确定何时插入元数据,但我怀疑您遇到了一个常见的误解。要发送到客户端的第一个数据应该是流数据,而不是元数据。流数据需要以您的元间隔响应标头指定的增量发送。

[24,576 bytes of stream] [metablock] [24,576 bytes of stream] [metablock] etc.

最后,您错误地填充了元块。不要使用文字0,使用NUL字节。 0x00.

于 2014-02-28T01:19:56.150 回答