Запись музыкального потока Python
Я хотел бы реализовать сервер в Python, который передает музыку в формате MP3 через HTTP. Я хотел бы, чтобы он транслировал музыку таким образом, чтобы клиент мог подключиться к потоку и начать слушать то, что в настоящее время играет, подобно радиостанции.
Раньше я реализовал свой собственный HTTP-сервер в Python с помощью SocketServer.TCPServer(да, я знаю, что BaseHTTPServer существует, просто хотел написать сам мини-HTTP-стек), так как бы музыкальный стример был бы по-другому архитектурным? Какие библиотеки мне нужно будет смотреть на стороне сети и на стороне MP3?
Ответы
Ответ 1
Формат mp3 был разработан для потоковой передачи, что делает некоторые вещи проще, чем вы могли ожидать. Данные представляют собой поток звуковых кадров со встроенными маркерами границ, а не заголовок файла, за которым следуют необработанные данные. Это означает, что, как только клиент ожидает получить аудиоданные, вы можете просто начать отправлять его байты из любой точки в существующем mp3-источнике, будь то вживую или файл, и клиент будет синхронизироваться до следующего найденного кадра и начать воспроизведение звука. Ура!
Конечно, вам нужно будет предоставить клиентам способ настроить соединение. Стандартом де-факто является протокол SHOUTcast (ICY). Это очень похоже на HTTP, но с полями состояния и заголовка, достаточно различающимися, что он напрямую не совместим с встроенными библиотеками http-серверов Python. Возможно, вы сможете получить эти библиотеки для выполнения какой-либо работы для вас, но их документированных интерфейсов будет недостаточно, чтобы сделать это; вам нужно будет прочитать их код, чтобы понять, как заставить их говорить SHOUTcast.
Вот несколько ссылок, которые помогут вам начать:
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
Я предлагаю начать с одного mp3 файла в качестве источника данных, наладить настройку и воспроизведение соединения клиент-сервер, а затем перейти к таким проблемам, как прямые источники, множественные скорости кодирования, внутриполосные метаданные и плейлисты.
Плейлисты, как правило, являются файлами .pls или .m3u и, по существу, просто статическими текстовыми файлами, указывающими на URL-адрес вашего прямого потока. Они не сложны и даже не нужны, потому что многие (большинство?) Потоковых клиентов mp3 будут принимать URL в реальном времени без плейлиста.
Что касается архитектуры, поле довольно широко раскрыто. У вас столько вариантов, сколько есть для HTTP-серверов. Ходовой? Рабочие процессы? Событие обусловлено? Это вам. Для меня более интересным является вопрос о том, как делиться данными из одного входного потока (вещателя) с сетевыми обработчиками, обслуживающими несколько выходных потоков (игроков). Чтобы избежать осложнений IPC и синхронизации, я, вероятно, начинал бы с однопоточного проекта, управляемого событиями. В python 2 библиотека, подобная gevent, даст вам очень хороший I/O, позволяя вам структурировать код очень понятным образом. В python 3 я бы предпочел asyncio сопрограммы.
Ответ 2
Поскольку у вас уже есть хороший опыт работы с python (если вы уже написали HTTP-сервер), я могу предоставить лишь несколько указаний о том, как расширить работу, которую вы уже сделали:
-
Подготовьте свой сервер для к заголовкам запроса, например: Accept-Encoding
, Range
, TE (Transfer Encoding)
и т.д. Игрок MP3-over-HTTP (т.е. VLC) ничего но mp3-плеер, который знает, как "говорить" HTTP и "искать" в разных позициях в файле.
-
Использовать wirehark или tcpdump для нюхать фактические HTTP-запросы, выполняемые VLC при воспроизведении mp3 через HTTP, поэтому вы знаете, как будут обрабатывать заголовки запросов и выполнять их.
Удачи вам в вашем проекте!
Ответ 3
Вы хотите посмотреть на m3u или pls. Это должно дать вам формат файла, который игроки понимают достаточно хорошо, чтобы поразить ваш http-сервер, ища mp3 файлы.
Минимальный файл m3u будет просто простым текстовым файлом с одним URL-адресом для каждой строки. Предполагая, что на вашем сервере доступны следующие URL-адреса:
/playlists/<playlist_name/playlist_id>
/songs/<song_name/song_id>
Вы будете показывать список воспроизведения из URL:
/playlists/myfirstplaylist
И содержимое ресурса будет просто:
/songs/1
/songs/mysong.mp3
Игрок (например, Winamp) сможет открыть URL-адрес файла m3u на вашем HTTP-сервере и затем начнет передавать первую песню в списке воспроизведения. Все, что вам нужно сделать, чтобы поддержать это, - это использовать mp3 файл так же, как и любой другой статический контент.
В зависимости от того, сколько клиентов вы хотите поддерживать, вы можете посмотреть асинхронный ввод-вывод, используя библиотеку, например Twisted, чтобы поддерживать тонны одновременные потоки.
Ответ 4
Изучите их, прежде чем заходить слишком далеко:
http://wiki.python.org/moin/PythonInMusic
В частности
http://edna.sourceforge.net/
Ответ 5
Вы хотите иметь файл .m3u или .pls, который указывает на статический URI (например, http://example.com/now_playing.mp3), затем дайте им mp3-данные начинаются везде, где вы находитесь в песне, когда они запрашивают этот файл. Вероятно, есть несколько мелких проблем, которые я замалчиваю здесь... Однако, по крайней мере, поскольку лес указывает, вы можете просто начать потоковое воспроизведение mp3-данных из любого байта.