Загрузка и обработка MP3-потока интернет-радио на Python

Вопросы и ответы

Я хотел бы написать программу на python, которая загружает интернет-радио mp3 поток, обрабатывает данные и воспроизводит аудиопоток на компьютере.

Мне не удалось найти способ сделать это правильно. На данный момент я использую этот код для чтения данных потока блоками:

for block in r.iter_content(1024):
   ... обработать блок

Затем я могу обрабатывать эти блоки с помощью библиотеки soundfile, и они читаются правильно как mp3:

stream_bytes = io.BytesIO()
stream_bytes.write(block)
...
# после записи нескольких блоков конвертируем mp3 данные в аудиоданные и частоту дискретизации:
data, samplerate = soundfile.read(stream_bytes)
print(f'{samplerate} {len(data)}')

Тогда я знаю, что могу воспроизвести аудио с помощью библиотеки pyaudio, инициализировав ее с той же определённой частотой дискретизации, количеством каналов и отправив аудиоданные.

Хотя здесь я не знаю, как:

  1. Как обрабатывать сам поток по мере его поступления. То есть, я не могу просто добавлять данные в файл stream_bytes и увеличивать его размер бесконечно, мне нужно как-то обрезать его, но как управлять ‘заголовками’ файла, чтобы он по-прежнему оставался распознаваемым как mp3? Как его обрезать или как сделать так, чтобы soundfile принимал новые ‘байты’? Я не вижу примеров потоковой передачи данных.
  2. Конвертировать данные из soundfile в байтовые данные, приемлемые для pyaudio (но я как-нибудь с этим справлюсь)

Ответ

Для загрузки и обработки интернет-радио MP3 потока в Python, а также для воспроизведения этого потока, мы можем использовать несколько библиотек, таких как requests, io, pydub для обработки звука, и pyaudio для воспроизведения аудио. Вот пошаговое руководство, как это сделать.

  1. Установка необходимых библиотек:
    Убедитесь, что у вас установлены следующие библиотеки. Вы можете установить их с помощью pip:

    pip install requests pydub pyaudio
  2. Загрузка и обработка потока:
    Мы будем использовать библиотеку requests для загрузки потока. В то время как pydub поможет нам с распознаванием и декодированием MP3 данных. Из-за того что потоки могут быть бесконечными, нам нужно обрабатывать их по блокам. Мы будем использовать AudioSegment из pydub для обработки каждого блока.

  3. Воспроизведение аудио с помощью PyAudio:
    После обработки данных мы будем воспроизводить их с помощью pyaudio.

Вот пример кода, который выполняет все эти шаги:

import requests
import io
from pydub import AudioSegment
import pyaudio
import numpy as np

# URL интернет-радио
url = "http://stream-url"  # Замените на ваш URL

# Параметры для воспроизведения
chunk_size = 1024  # Размер блока
p = pyaudio.PyAudio()

# Открытие потока
stream = p.open(format=pyaudio.paInt16,
                 channels=2,
                 rate=44100,
                 output=True)

# Создаем поток для запроса
with requests.get(url, stream=True) as r:
    r.raise_for_status()

    stream_bytes = bytes()  # Хранилище для данных потока
    for block in r.iter_content(chunk_size=chunk_size):
        stream_bytes += block  # Добавляем блок к нашим данным

        try:
            # Пробуем преобразовать данные в AudioSegment
            audio_segment = AudioSegment.from_mp3(io.BytesIO(stream_bytes))
            # Получаем данные и преобразуем их в массив numpy
            raw_data = audio_segment.raw_data

            # Воспроизводим аудио
            stream.write(raw_data)

            # Очищаем stream_bytes, оставляя только последние 10 секунд (параметр в миллисекундах)
            if len(stream_bytes) > 44100 * 2 * 2 * 10:  # 44100 * 2 (стерео) * 2 (байта на сэмпл) * 10 секунд
                stream_bytes = stream_bytes[-(44100 * 2 * 2 * 10):]  # Оставляем последние 10 секунд
        except Exception as e:
            print(f"Ошибка при обработке: {e}")
            continue

# Завершение работы
stream.stop_stream()
stream.close()
p.terminate()

Объяснение работы кода:

  1. Загрузка потока: Мы используем requests.get() для подключения к интернет-радио и получаем поток данных.
  2. Обработка потока: В каждом цикле мы добавляем блок данных к stream_bytes. Затем мы пытаемся преобразовать эти данные в AudioSegment. Если преобразование успешное, мы извлекаем необработанные данные и воспроизводим их.
  3. Ограничение размера буфера: Мы сохраняем только последние 10 секунд данных в stream_bytes, чтобы избежать переполнения памяти. Вы можете изменить этот временной интервал на свое усмотрение.
  4. Воспроизведение: Используя PyAudio, мы воспроизводим необработанные данные аудиосегмента.

Обратите внимание:

  • В зависимости от вашего потока радиостанции, вам может понадобиться установить правильный формат, каналы и частоту дискретизации для PyAudio.
  • Обработку ошибок следует адаптировать под вашу конкретную ситуацию для более надежного выполнения.

Теперь у вас есть полное решение для загрузки, обработки и воспроизведения интернет-радио MP3 потока в Python.

Оцените материал
Добавить комментарий

Капча загружается...