第七色在线视频,2021少妇久久久久久久久久,亚洲欧洲精品成人久久av18,亚洲国产精品特色大片观看完整版,孙宇晨将参加特朗普的晚宴

為了賬號(hào)安全,請(qǐng)及時(shí)綁定郵箱和手機(jī)立即綁定
已解決430363個(gè)問(wèn)題,去搜搜看,總會(huì)有你想問(wèn)的

如何使用 Python 接收“icecast”互聯(lián)網(wǎng)廣播流以立即播放?

如何使用 Python 接收“icecast”互聯(lián)網(wǎng)廣播流以立即播放?

開(kāi)心每一天1111 2022-04-27 16:11:16
我想要一個(gè)互聯(lián)網(wǎng)音頻/廣播流(特別是Longplayer,點(diǎn)擊直接流 URL)并用 python 播放它。最好是后臺(tái)運(yùn)行,以便腳本能夠繼續(xù)運(yùn)行其主循環(huán)。(例如作為游戲背景音樂(lè)或其他東西,雖然 Pyglet、PyGame 等可能為此提供自己的工具。)我已經(jīng)看到了一些可能已過(guò)時(shí)的示例,這些示例使用錄制互聯(lián)網(wǎng)廣播requests并將其轉(zhuǎn)儲(chǔ)到文件中,但這并不是我想要的,而且答案的評(píng)論似乎有關(guān)于requests存在問(wèn)題的爭(zhēng)論?(見(jiàn)這里)我愿意使用任何你可以使用的包pip,只要它適用于 Python 3.X。(目前使用 3.6 純粹是因?yàn)槲疫€沒(méi)有努力安裝 3.7)重申一下,我不想保存流,只需立即播放(或者在需要時(shí)使用緩沖?)回給用戶(hù)。這最好是不阻塞腳本,我想這需要多線程/多處理,但這對(duì)于播放來(lái)說(shuō)是次要的。)
查看完整描述

2 回答

?
吃雞游戲

TA貢獻(xiàn)1829條經(jīng)驗(yàn) 獲得超7個(gè)贊

正如這些看似簡(jiǎn)單的問(wèn)題似乎總是如此,魔鬼在細(xì)節(jié)中。我最終寫(xiě)了一些代碼來(lái)解決這個(gè)問(wèn)題。pip 依賴(lài)項(xiàng)可以使用python3 -m pip install ffmpeg-python PyOpenAL. 代碼的工作流程可以分為兩步:

  1. 代碼必須從在線流中下載 mp3 文件數(shù)據(jù)的二進(jìn)制塊,并將它們轉(zhuǎn)換為原始 PCM 數(shù)據(jù)(基本上是簽名的 uint16_t 幅度值)以進(jìn)行播放。這是使用ffmpeg-python 庫(kù)完成的,它是FFmpeg的包裝器。此包裝器在單獨(dú)的進(jìn)程中運(yùn)行 FFmpeg,因此此處不會(huì)發(fā)生阻塞。

  2. 然后代碼必須將這些塊排隊(duì)以進(jìn)行播放。這是使用PyOpenAL完成的,它是OpenAL的包裝器。在創(chuàng)建設(shè)備和上下文以啟用音頻播放后,將創(chuàng)建一個(gè) 3d 定位的源。這個(gè)源不斷地與緩沖區(qū)(模擬“環(huán)形緩沖區(qū)”)一起排隊(duì),這些緩沖區(qū)填充了從 FFmpeg 輸入的數(shù)據(jù)。這與第一步在單獨(dú)的線程上運(yùn)行,使下載新音頻塊獨(dú)立于音頻塊播放運(yùn)行。

這是該代碼的樣子(帶有一些注釋?zhuān)H绻鷮?duì)代碼或此答案的任何其他部分有任何疑問(wèn),請(qǐng)告訴我。

import ctypes

import ffmpeg

import numpy as np

from openal.al import *

from openal.alc import *

from queue import Queue, Empty

from threading import Thread

import time

from urllib.request import urlopen


def init_audio():

    #Create an OpenAL device and context.

    device_name = alcGetString(None, ALC_DEFAULT_DEVICE_SPECIFIER)

    device = alcOpenDevice(device_name)

    context = alcCreateContext(device, None)

    alcMakeContextCurrent(context)

    return (device, context)


def create_audio_source():

    #Create an OpenAL source.

    source = ctypes.c_uint()

    alGenSources(1, ctypes.pointer(source))

    return source


def create_audio_buffers(num_buffers):

    #Create a ctypes array of OpenAL buffers.

    buffers = (ctypes.c_uint * num_buffers)()

    buffers_ptr = ctypes.cast(

        ctypes.pointer(buffers), 

        ctypes.POINTER(ctypes.c_uint),

    )

    alGenBuffers(num_buffers, buffers_ptr)

    return buffers_ptr


def fill_audio_buffer(buffer_id, chunk):

    #Fill an OpenAL buffer with a chunk of PCM data.

    alBufferData(buffer_id, AL_FORMAT_STEREO16, chunk, len(chunk), 44100)


def get_audio_chunk(process, chunk_size):

    #Fetch a chunk of PCM data from the FFMPEG process.

    return process.stdout.read(chunk_size)


def play_audio(process):

    #Queues up PCM chunks for playing through OpenAL

    num_buffers = 4

    chunk_size = 8192

    device, context = init_audio()

    source = create_audio_source()

    buffers = create_audio_buffers(num_buffers)


    #Initialize the OpenAL buffers with some chunks

    for i in range(num_buffers):

        buffer_id = ctypes.c_uint(buffers[i])

        chunk = get_audio_chunk(process, chunk_size)

        fill_audio_buffer(buffer_id, chunk)


    #Queue the OpenAL buffers into the OpenAL source and start playing sound!

    alSourceQueueBuffers(source, num_buffers, buffers)

    alSourcePlay(source)

    num_used_buffers = ctypes.pointer(ctypes.c_int())


    while True:

        #Check if any buffers are used up/processed and refill them with data.

        alGetSourcei(source, AL_BUFFERS_PROCESSED, num_used_buffers)

        if num_used_buffers.contents.value != 0:

            used_buffer_id = ctypes.c_uint()

            used_buffer_ptr = ctypes.pointer(used_buffer_id)

            alSourceUnqueueBuffers(source, 1, used_buffer_ptr)

            chunk = get_audio_chunk(process, chunk_size)

            fill_audio_buffer(used_buffer_id, chunk)

            alSourceQueueBuffers(source, 1, used_buffer_ptr)


if __name__ == "__main__":    

    url = "http://icecast.spc.org:8000/longplayer"


    #Run FFMPEG in a separate process using subprocess, so it is non-blocking

    process = (

        ffmpeg

        .input(url)

        .output("pipe:", format='s16le', acodec='pcm_s16le', ac=2, ar=44100, loglevel="quiet")

        .run_async(pipe_stdout=True)

    )


    #Run audio playing OpenAL code in a separate thread

    thread = Thread(target=play_audio, args=(process,), daemon=True)

    thread.start()


    #Some example code to show that this is not being blocked by the audio.

    start = time.time()

    while True:

        print(time.time() - start)


查看完整回答
反對(duì) 回復(fù) 2022-04-27
?
慕姐8265434

TA貢獻(xiàn)1813條經(jīng)驗(yàn) 獲得超2個(gè)贊

使用pyminiaudio : (它提供了一個(gè) icecast 流源類(lèi)):


import miniaudio


def title_printer(client: miniaudio.IceCastClient, new_title: str) -> None:

    print("Stream title: ", new_title)


with miniaudio.IceCastClient("http://icecast.spc.org:8000/longplayer",

        update_stream_title=title_printer) as source:

    print("Connected to internet stream, audio format:", source.audio_format.name)

    print("Station name: ", source.station_name)

    print("Station genre: ", source.station_genre)

    print("Press <enter> to quit playing.\n")

    stream = miniaudio.stream_any(source, source.audio_format)

    with miniaudio.PlaybackDevice() as device:

        device.start(stream)

        input()   # wait for user input, stream plays in background


查看完整回答
反對(duì) 回復(fù) 2022-04-27
  • 2 回答
  • 0 關(guān)注
  • 195 瀏覽
慕課專(zhuān)欄
更多

添加回答

舉報(bào)

0/150
提交
取消
微信客服

購(gòu)課補(bǔ)貼
聯(lián)系客服咨詢(xún)優(yōu)惠詳情

幫助反饋 APP下載

慕課網(wǎng)APP
您的移動(dòng)學(xué)習(xí)伙伴

公眾號(hào)

掃描二維碼
關(guān)注慕課網(wǎng)微信公眾號(hào)