簡體   English   中英

Java中的SHOUTcast服務器

[英]SHOUTcast server in Java

我正在用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一起使用,所以我在做錯什么嗎?

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-元數據= 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

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM