Escribiendo un Streamer de música Python
http streaming (5)
Me gustaría implementar un servidor en Python que transmita música en formato MP3 a través de HTTP. Me gustaría que transmita la música de tal manera que un cliente pueda conectarse a la transmisión y comenzar a escuchar lo que se esté reproduciendo, como una estación de radio.
Anteriormente, he implementado mi propio servidor HTTP en Python usando SocketServer.TCPServer (sí, sé que BaseHTTPServer existe, solo quería escribir una mini pila HTTP), entonces, ¿cómo sería diferente la arquitectura de un transmisor de música? ¿Qué bibliotecas necesitaría mirar en el lado de la red y en el lado de MP3?
Como ya tienes una buena experiencia con Python (dado que ya has escrito un servidor HTTP), solo puedo darte algunos consejos sobre cómo extender el trabajo de campo que ya has hecho:
Prepare su servidor para tratar con Encabezados de Solicitud como:
Accept-Encoding
,Range
,TE (Transfer Encoding)
, etc. Un reproductor de MP3 sobre HTTP (es decir, VLC) no es más que un reproductor de mp3 que sabe cómo "hablar" HTTP y "buscar" a diferentes posiciones en el archivo.Use wireshark o tcpdump para rastrear las solicitudes HTTP reales realizadas por VLC cuando se reproduce un mp3 a través de HTTP, para que sepa cómo las cabeceras de solicitudes las recibirá y las implementará.
¡Buena suerte con tu proyecto!
El formato mp3 fue diseñado para la transmisión, lo que hace que algunas cosas sean más simples de lo que podría haber esperado. Los datos son esencialmente un flujo de cuadros de audio con marcadores de límites integrados, en lugar de un encabezado de archivo seguido de datos sin procesar. Esto significa que una vez que un cliente está esperando recibir datos de audio, puede comenzar a enviar bytes desde cualquier punto en una fuente de mp3 existente, ya sea en vivo o en un archivo, y el cliente se sincronizará con el siguiente fotograma que encuentre y empieza a reproducir audio ¡Hurra!
Por supuesto, tendrá que dar a los clientes una forma de configurar la conexión. El estándar de facto es el protocolo SHOUTcast (ICY). Esto es muy parecido a HTTP, pero con los campos de estado y encabezado lo suficientemente diferentes como para que no sea directamente compatible con las bibliotecas de servidores http incorporadas de Python. Es posible que pueda hacer que esas bibliotecas realicen parte del trabajo por usted, pero sus interfaces documentadas no serán suficientes para hacerlo; Tendrás que leer su código para entender cómo hacer que hablen SHOUTcast.
Aquí hay algunos enlaces para comenzar:
http://forums.winamp.com/showthread.php?threadid=70403
http://forums.radiotoolbox.com/viewtopic.php?t=74
http://www.smackfu.com/stuff/programming/shoutcast.html
http://en.wikipedia.org/wiki/Shoutcast
Sugiero comenzar con un solo archivo mp3 como su fuente de datos, hacer que la configuración de conexión y reproducción del cliente-servidor funcione, y luego pasar a temas como fuentes en vivo, múltiples tasas de bits de codificación, metadatos en banda y listas de reproducción.
Las listas de reproducción generalmente son archivos .pls o .m3u, y esencialmente solo archivos de texto estático que apuntan a la URL de su transmisión en vivo. No son difíciles y ni siquiera estrictamente necesarios, ya que muchos (¿la mayoría?) Los clientes de transmisión de mp3 aceptarán una URL de transmisión en vivo sin ninguna lista de reproducción.
En cuanto a la arquitectura, el campo está bastante abierto. Tienes tantas opciones como hay para los servidores HTTP. ¿Roscado? ¿Procesos de trabajo? ¿Evento conducido? Tu decides. Para mí, la pregunta más interesante es cómo compartir los datos de un solo flujo de entrada (la emisora) con los controladores de red que sirven a múltiples flujos de salida (los jugadores). Para evitar complicaciones de IPC y sincronización, probablemente comenzaría con un diseño basado en eventos de un solo hilo. En Python 2, una biblioteca como gevent te dará muy buen rendimiento de E / S y te permitirá estructurar tu código de una manera muy comprensible. En python 3, preferiría asyncio coroutines.
Estudia estos antes de llegar demasiado lejos:
http://wiki.python.org/moin/PythonInMusic
Específicamente
Querrá tener un archivo .m3u o .pls que apunte a una URI estática (p. Ej., http://example.com/now_playing.mp3 ) y luego darles datos en MP3 desde cualquier lugar de la canción cuando lo soliciten. expediente. Probablemente hay un montón de problemas menores que estoy ocultando aquí ... Sin embargo, al menos como señala el bosque, puedes comenzar a transmitir los datos mp3 desde cualquier byte.
Usted querrá mirar en el servicio de archivos m3u o pls . Eso debería darle un formato de archivo que los jugadores entiendan lo suficientemente bien como para golpear su servidor http en busca de archivos mp3.
Un archivo m3u mínimo sería un simple archivo de texto con una url de canción por línea. Suponiendo que tenga las siguientes URL disponibles en su servidor:
/playlists/<playlist_name/playlist_id>
/songs/<song_name/song_id>
Servirías una lista de reproducción de la url:
/playlists/myfirstplaylist
Y el contenido del recurso sería justo:
/songs/1
/songs/mysong.mp3
Un jugador (como Winamp) podrá abrir la URL al archivo m3u en su servidor HTTP y luego iniciará la transmisión de la primera canción en la lista de reproducción. Todo lo que tendrá que hacer para admitir esto es servir el archivo mp3 tal como lo haría con cualquier otro contenido estático.
Dependiendo de la cantidad de clientes que desee admitir, es posible que desee buscar IO asíncronas utilizando una biblioteca como Twisted para admitir toneladas de flujos simultáneos.