简体   繁体   English

使用python流mp3 icecast数据

[英]Stream mp3 icecast data using python

I'm trying to write my own socket streamer where I connect to a know mp3 source using python's socket, stream the data and try and pass it into alsaaudio as pcm data. 我正在尝试编写自己的套接字流媒体,在这里我使用python的套接字连接到已知的mp3源,传输数据并将其作为pcm数据传递到alsaaudio中。

I know have to get the icy-metaint, read that many bytes, get the first byte for the metadata length then continue reading metaint bytes. 我知道必须获取icy-metaint,读取那么多字节,获取元数据长度的第一个字节,然后继续读取metaint字节。

Unfortunately I've run out of knowlege and the code below results in white noise being played. 不幸的是,我用完了所有的知识,下面的代码导致播放白噪声。

Any help would be amazing. 任何帮助都将是惊人的。 Thank you! 谢谢!

#!/usr/bin/env python
import socket
import sys
import alsaaudio
import time
import threading
import Queue

class Player(threading.Thread):

    def __init__(self, messageQueue, metaint):
        threading.Thread.__init__(self)

        self.metaint = metaint

        self.messageQueue = messageQueue
        self.device = alsaaudio.PCM()
        self.rate = 44100
        self.famesize = self.rate 
        self.device.setrate(self.rate)
        self.buffer = ""

    def sendPCM(self):
        print("Buffer length: " + str(len(self.buffer)))
        if len(self.buffer) > self.metaint + 255:
            pcmData = self.buffer[:self.metaint]
            self.device.write(pcmData)
            self.buffer = self.buffer[self.metaint:]
            print ("New buffer length 1: " + str(len(self.buffer)))
            metaDataLength = ord(self.buffer[:1]) * 16
            print ("Metadata length: " + str(metaDataLength))
            self.buffer = self.buffer[1:]
            print ("New buffer length 2: " + str(len(self.buffer)))
            metaData = self.buffer[:metaDataLength]
            print len(metaData)
            self.buffer = self.buffer[metaDataLength:]
            print ("New buffer length 3: " + str(len(self.buffer)))


    def run(self):
        self.sendPCM()
        while True:
            message = self.messageQueue.get()
            if message: self.buffer += message
            self.sendPCM()
            self.messageQueue.task_done()

def getResponseHeaders(socket):
    data = socket.recv(1024)

    while not "\r\n\r\n" in data:
        data = data + socket.recv(1024)

    return data

def getHeaders(response):
    headers = {}
    for line in response.splitlines():
        if line == '\r\n':
            break # end of headers
        if ':' in line:
            key, value = line.split(':', 1)
            headers[key] = value

    return headers


HOST = 'bbcmedia.ic.llnwd.net'
GET = '/stream/bbcmedia_lc1_radio1_p?s=1420917253&e=1420931653&h=1ff16ea945bd420669c48ae72d003c09'
PORT = 80

#create an INET, STREAMing socket
client_socket = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
client_socket.connect((HOST, PORT))
client_socket.send("GET %s HTTP/1.0\r\nHost: %s\r\nUser-Agent:%s\r\nIcy-MetaData:%s\r\nRange:%s\r\n\r\n" % (GET, HOST,"VLC/2.0.5 LibVLC/2.0.5", "1", "bytes=0-"))

responseHeaders = getResponseHeaders(client_socket)
headers = getHeaders(responseHeaders)
metaint = int(headers['icy-metaint'])
br = int(headers['icy-br'])
print (metaint)



queue = Queue.Queue()

player = Player(queue, metaint)
player.daemon = True
player.start()

while 1:
    queue.put(client_socket.recv(4096))


client_socket.close()
sys.exit(0)

It doesn't look like you are actually decoding the audio data. 看起来您实际上不是在解码音频数据。

You are attempting to demux the audio data from the metadata, but you must also run the audio data through the codec to get PCM samples. 您正在尝试从元数据中解复用音频数据,但还必须通过编解码器运行音频数据以获取PCM样本。 SHOUTcast/Icecast servers do not send raw PCM. SHOUTcast / Icecast服务器不发送原始PCM。 They usually use MP3 or AAC wrapped in ADTS. 他们通常使用包装在ADTS中的MP3或AAC。

I'm not a Python coder so I do not know what all you have available to you. 我不是Python编码员,所以我不知道您拥有什么。 An easy way to decode is to use FFmpeg. 一种简单的解码方法是使用FFmpeg。 It supports STDIO, so you can easily pipe data to it and let it handle the stream and return PCM samples. 它支持STDIO,因此您可以轻松地将数据传输到它,并让它处理流并返回PCM样本。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM