我正在用Java开发一台shoutcast服务器,遇到了麻烦。如果我向客户端(VLC / WINAMP)发送HTTP响应,则服务器可以很好地传输数据:

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


然后开始流式传输文件。但是,当我向客户端发送ICY响应时,声音开始变得有点杂音和吱吱作响,有时播放的速度有点快。有时,它会同时播放播放列表中所有歌曲中的一些小片段,但是如果我断开客户端连接并再次连接,它会正确播放,在这种情况下会有点断断续续。我尝试连接到Internet上的广播服务器,它们似乎完美无缺。 (我还将以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


然后,我将String转换为字节,并将那些标头字节写入流中,然后写入24kb块,然后标头,依此类推。这似乎根本没有帮助。 SHOUTcast可以很好地与ICEcast一起使用,所以我在做错什么吗?

附注:我知道代码看起来有些混乱,可能会更好,但这只是一个测试。我还发送此常量字符串作为测试,以查看是否有帮助。该计划是在可行的情况下正确执行。

任何帮助表示赞赏。

我的信息是从


http://ample.sourceforge.net/developers.shtml
http://www.smackfu.com/stuff/programming/shoutcast.html


编辑:

这就是我确定何时发送字节的方式(此代码在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-元数据= 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

09-28 03:44