Tocar áudio com Python

107

Como posso reproduzir áudio (seria como um som de 1 segundo) de um script Python?

Seria melhor se fosse independente de plataforma, mas primeiro precisa funcionar em um Mac.

Eu sei que poderia simplesmente executar o afplay file.mp3comando de dentro do Python, mas é possível fazer isso no Python bruto? Eu também seria melhor se não dependesse de bibliotecas externas.

Josh Hunt
fonte
Pyglet tem a capacidade de reproduzir áudio por meio de uma biblioteca externa chamada AVbin . Pyglet é um invólucro ctypes em torno de chamadas de sistema nativas em cada plataforma que suporta. Infelizmente, não acho que nada na biblioteca padrão reproduza áudio.
tecnomalógico
Se você precisa de uma biblioteca de áudio Python portátil, experimente o PyAudio . Certamente tem uma porta mac. Quanto aos arquivos mp3: certamente é possível em Python "bruto", mas infelizmente você terá que codificar tudo sozinho :). Se você puder pagar por alguma biblioteca externa, encontrei alguns exemplos de PyAudio - PyLame aqui.
Grzegorz Gacek

Respostas:

17

Você pode encontrar informações sobre o áudio Python aqui: http://wiki.python.org/moin/Audio/

Parece que não pode reproduzir arquivos .mp3 sem bibliotecas externas. Você pode converter seu arquivo .mp3 para .wav ou outro formato, ou usar uma biblioteca como o PyMedia .

Jeremy Ruten
fonte
12
Mas como faço para reproduzir um .wavarquivo?
theonlygusti
@theonlygusti Veja aqui , por exemplo.
Anderson Green
42

Provavelmente, sua melhor aposta é usar pygame / SDL . É uma biblioteca externa, mas tem ótimo suporte em várias plataformas.

pygame.mixer.init()
pygame.mixer.music.load("file.mp3")
pygame.mixer.music.play()

Você pode encontrar documentação mais específica sobre o suporte ao mixer de áudio na documentação do pygame.mixer.music

TML
fonte
2
Para mim, isso não estava funcionando. Quer dizer, estava tocando, mas sem som. Eu adicionei time.sleep(5)no final e funcionou. Python 3.6 no Windows 8.1
Nagabhushan SN de
Pacote de fogo! Obrigado!
Сергей Зеленчук
Não funciona no Fedora com os padrões ".wav", ".mp3" e ".ogg" (Não é possível abrir o arquivo 'filename.format')
Calvin-Ruiz
1
@ Calvin-Ruiz Acabei de confirmar que posso usar o código acima no FC31 para reproduzir arquivos MP3 e Ogg. Acho que você tem um problema maior que provavelmente precisa de algum conhecimento detalhado de sua plataforma.
TML
18

Dê uma olhada em Simpleaudio , que é uma biblioteca relativamente recente e leve para esta finalidade:

> pip install simpleaudio

Então:

import simpleaudio as sa

wave_obj = sa.WaveObject.from_wave_file("path/to/file.wav")
play_obj = wave_obj.play()
play_obj.wait_done()

Certifique-se de usar arquivos PCM de 16 bits não compactados.

Erwin Mayer
fonte
Legal, obrigado - útil para jogos que precisam reproduzir efeitos sonoros curtos e suporta Python 3.
Thomas Perl
18

Tente brincar que é um Pure Python, plataforma cruzada, módulo de função única sem dependências para reproduzir sons.

Instale via pip:

$ pip install playsound

Depois de instalar, você pode usá-lo assim:

from playsound import playsound
playsound('/path/to/a/sound/file/you/want/to/play.mp3')
Yehan Jaya
fonte
36
Ler isso me deixou tão emocionado. Meus olhos literalmente se encheram de lágrimas de felicidade. Não esperava esse tipo de reação de mim mesmo. (Eles vincularam a um módulo que eu fiz.)
ArtOfWarfare
1 para playsound. Acabei de testar algumas soluções aqui, e esta funcionou mais fácil para mim. Infelizmente a pygamesolução não funcionou para mim, durante um breve teste.
Trevor Sullivan
13

No pydub , recentemente optamos por usar ffplay (via subprocesso) do conjunto de ferramentas ffmpeg, que usa SDL internamente.

Funciona para nossos propósitos - principalmente apenas para facilitar o teste dos resultados do código pydub no modo interativo - mas tem suas desvantagens, como fazer com que um novo programa apareça no dock do mac.

Vinculei a implementação acima, mas segue uma versão simplificada:

import subprocess

def play(audio_file_path):
    subprocess.call(["ffplay", "-nodisp", "-autoexit", audio_file_path])

O -nodispsinalizador impede que o ffplay mostre uma nova janela e -autoexitfaz com que o ffplay saia e retorne um código de status quando o arquivo de áudio terminar de tocar.

edit : pydub agora usa pyaudio para reprodução quando está instalado e volta para ffplay para evitar as desvantagens que mencionei. O link acima mostra essa implementação também.

Jiaaro
fonte
1
Parece que o Pydub tem um grande potencial como uma biblioteca de wrapper - estou instalando agora.
Shadow
1
O maldito PyDub parece bom e ainda está muito ativo.
corysimmons
13

Desculpe pelo atraso na resposta, mas acho que este é um bom lugar para divulgar minha biblioteca ...

AFAIK, a biblioteca padrão tem apenas um módulo para reproduzir áudio: ossaudiodev . Infelizmente, isso só funciona no Linux e no FreeBSD.

ATUALIZAÇÃO: também há winound , mas obviamente também é específico da plataforma.

Para algo mais independente de plataforma, você precisará usar uma biblioteca externa.

Minha recomendação é o dispositivo de som módulo de dispositivo de (mas cuidado, eu sou o autor).

O pacote inclui a biblioteca PortAudio pré-compilada para Mac OS X e Windows e pode ser facilmente instalado com:

pip install sounddevice --user

Ele pode reproduzir sons de matrizes NumPy, mas também pode usar buffers Python simples (se NumPy não estiver disponível).

Para reproduzir uma matriz NumPy, isso é tudo que você precisa (assumindo que os dados de áudio tenham uma frequência de amostragem de 44100 Hz):

import sounddevice as sd
sd.play(myarray, 44100)

Para mais detalhes, dê uma olhada na documentação .

Ele não pode ler / gravar arquivos de som, você precisará de uma biblioteca separada para isso.

Matthias
fonte
Ótimo! Exatamente o que eu precisava para fazer um programa de demonstração da aula sobre ondas.
Bill N,
5

Você pode ver isso: http://www.speech.kth.se/snack/

s = Sound() 
s.read('sound.wav') 
s.play()
user1926182
fonte
3
Parece tão limpo, gostaria que houvesse um pacote pip para isso. Facilidade de instalação é fundamental
Jonathan
4

A resposta de Aaron parece ser cerca de 10 vezes mais complicada do que o necessário. Faça isso se precisar apenas de uma resposta que funcione no OS X:

from AppKit import NSSound

sound = NSSound.alloc()
sound.initWithContentsOfFile_byReference_('/path/to/file.wav', True)
sound.play()

Uma coisa ... isso retorna imediatamente. Portanto, você também pode fazer isso, se quiser que a chamada seja bloqueada até que o som termine de tocar.

from time import sleep

sleep(sound.duration())

Edit: Peguei esta função e combinei com variantes para Windows e Linux. O resultado é um Python puro, módulo de plataforma cruzada sem dependências, chamado playsound . Eu enviei para pypi.

pip install playsound

Em seguida, execute-o assim:

from playsound import playsound
playsound('/path/to/file.wav', block = False)

Os arquivos MP3 também funcionam no OS X. O WAV deve funcionar em todas as plataformas. Não sei que outras combinações de plataforma / formato de arquivo funcionam ou não - ainda não as experimentei.

ArtOfWarfare
fonte
Recebo o seguinte erro: "Não é possível converter o objeto 'bytes' em str implicitamente" no Python 3.5 (Windows).
Erwin Mayer
@ErwinMayer - Você está falando sobre o playsoundmódulo que escrevi? Eu não testei em nada mais recente que o Python 2.7.11 ... Eu certamente posso
tentar
De fato. Deve ser devido às diferenças do Python 3.
Erwin Mayer
O AppKit é uma dependência.
Chris Larson
2
@ArtOfWarfare Isso simplesmente não é verdade. Ele é instalado com o sistema python, mas não com a maioria das distribuições, incluindo as distribuições oficiais de python.org. A maioria das pessoas que conheço que usam python instalam uma das distribuições para superar as restrições SIP. Para obter o AppKit para a maioria das distribuições, um usuário precisa instalar o pyobjc. O que o torna definitivamente uma dependência.
Chris Larson
3

Este é o iv'e mais fácil e melhor encontrado. Ele suporta Linux / pulseaudio, Mac / coreaudio e Windows / WASAPI.

import soundfile as sf
import soundcard as sc

default_speaker = sc.default_speaker()
samples, samplerate = sf.read('bell.wav')

default_speaker.play(samples, samplerate=samplerate)

Veja https://github.com/bastibe/PySoundFile e https://github.com/bastibe/SoundCard para toneladas de outros recursos superúteis.

n00p
fonte
Apenas um aviso para quem está indo para isso (como eu). Todas as bibliotecas e suas dependências levam uma eternidade para serem compiladas em um Raspberry Pi 1B + - especialmente numpy.
pojda
PS: isso não funcionou para o raspberry pi "NotImplementedError: SoundCard ainda não oferece suporte a linux2" e não conseguiu descobrir uma maneira de consertar. Vou com os.system ("mpg123 file.mp3")
pojda
Ah, isso é péssimo. Eu acho que o framboesa pi é um ambiente um tanto especial. Talvez se você postar um problema no issuetracker, possa resolvê-lo ou consertá-lo.
n00p
Pensando melhor, talvez o problema seja que você está usando um kernel antigo ou uma versão antiga do python. Com as versões mais recentes do python, esse erro não deve ser assim, eu acho.
n00p de
Ele está executando o Raspbian, que é basicamente um fork do Debian Stretch. Desisti e segui o caminho os.system, que está funcionando perfeitamente no atm. Obrigado por me ajudar!
pojda de
2

É possível reproduzir áudio no OS X sem nenhuma biblioteca de terceiros usando um análogo do código a seguir. Os dados de áudio brutos podem ser inseridos com wave_wave.writeframes. Este código extrai 4 segundos de áudio do arquivo de entrada.

import wave
import io
from AppKit import NSSound


wave_output = io.BytesIO()
wave_shell = wave.open(wave_output, mode="wb")
file_path = 'SINE.WAV'
input_audio = wave.open(file_path)
input_audio_frames = input_audio.readframes(input_audio.getnframes())

wave_shell.setnchannels(input_audio.getnchannels())
wave_shell.setsampwidth(input_audio.getsampwidth())
wave_shell.setframerate(input_audio.getframerate())

seconds_multiplier = input_audio.getnchannels() * input_audio.getsampwidth() * input_audio.getframerate()

wave_shell.writeframes(input_audio_frames[second_multiplier:second_multiplier*5])

wave_shell.close()

wave_output.seek(0)
wave_data = wave_output.read()
audio_stream = NSSound.alloc()
audio_stream.initWithData_(wave_data)
audio_stream.play()
Aaron
fonte
Isso é muito mais complicado do que o necessário - eles perguntaram como simplesmente tocar um som, não como manipulá-lo e depois tocá-lo. Minha resposta elimina os 90% desnecessários dessa resposta e deixa exatamente o que o autor da pergunta queria - reproduzir um som de um arquivo no OS X usando Python. stackoverflow.com/a/34984200/901641
ArtOfWarfare
2

Experimente o PySoundCard que usa PortAudio para reprodução, disponível em muitas plataformas. Além disso, reconhece dispositivos de som "profissionais" com muitos canais.

Aqui está um pequeno exemplo do Leiame:

from pysoundcard import Stream

"""Loop back five seconds of audio data."""

fs = 44100
blocksize = 16
s = Stream(samplerate=fs, blocksize=blocksize)
s.start()
for n in range(int(fs*5/blocksize)):
    s.write(s.read(blocksize))
s.stop()
Stefan Balke
fonte
Embora interessantes, respostas apenas com links são desencorajadas. No mínimo, você deve incluir em sua resposta um breve exemplo de como usá-lo. Isso também protege sua resposta de perder todo o seu valor, caso o repositório seja renomeado e o link fique pendente.
spectras
2

Também no OSX - a partir do SO , usando o comando afplay do OSX :

import subprocess
subprocess.call(["afplay", "path/to/audio/file"])

ATUALIZAÇÃO: tudo isso especifica como fazer o que o OP queria evitar fazer em primeiro lugar. Acho que postei isso aqui porque o que OP queria evitar era a informação que eu estava procurando. Opa.

MikeiLL
fonte
Funciona muito bem, mas faz uma pausa na execução durante a reprodução. Talvez haja uma maneira assíncrona de chamar isso?
Praxiteles
Boas perguntas @Praxiteles. Possivelmente com rosca. veja aqui. Relate se você tiver a chance de experimentar.
MikeiLL
O OP pediu explicitamente alternativas para isso.
whitey04 de
O OP está / estava procurando uma alternativa para "executar o comando afplay file.mp3 de dentro do Python", e o subprocessamento ainda acontece dentro do Python, não é? Eu estou corrigido. Mas provavelmente não faz mal ter este pequeno post aqui, pois pode ajudar outras pessoas.
MikeiLL
@ whitey04 Eu (finalmente) entendi o que você está dizendo.
MikeiLL de
1

Pypi tem uma lista de módulos para python na música. Meu favorito seria jython porque ele tem mais recursos e bibliotecas para música. Como exemplo de código para tocar uma única nota do livro :

# playNote.py 
# Demonstrates how to play a single note.

from music import *   # import music library
note = Note(C4, HN)   # create a middle C half note 
Play.midi(note)       # and play it!
Kardi Teknomo
fonte
1

Mac OS Eu tentei vários códigos, mas isso funciona comigo

import pygame
import time
pygame.mixer.init()
pygame.init()
pygame.mixer.music.load('fire alarm sound.mp3') *On my project folder*
i = 0
while i<10:
    pygame.mixer.music.play(loops=10, start=0.0)
    time.sleep(10)*to protect from closing*
    pygame.mixer.music.set_volume(10)
    i = i + 1
Capitão django
fonte
1

Instale o playsoundpacote usando:

pip install playsound

Uso:

from playsound import playsound
playsound("file location\audio.p3")
Harish
fonte
0
Coloque isso no topo do seu script Python que você está escrevendo:
import subprocess
Se o arquivo wav estiver no diretório do script Python:
f = './mySound.wav'
subprocess.Popen(['aplay','-q',f)
Se o arquivo wav NÃO ESTÁ no diretório do script Python:
f = 'mySound.wav'
subprocess.Popen(['aplay','-q', 'wav/' + f)
Se você quiser saber mais sobre aplay:
man aplay
Crawsome
fonte
0

Para reproduzir um som de notificação usando python, chame um reprodutor de música, como vlc. O VLC me pediu para usar sua versão de linha de comando, cvlc, em vez disso.

from subprocess import call
call(["cvlc", "--play-and-exit", "myNotificationTone.mp3"])

Requer que o vlc esteja pré-instalado no dispositivo. Testado em Linux (Ubuntu 16.04 LTS); Executando Python 3.5.

amar Vashishth
fonte
0

Experimente o dispositivo de som

Se você não tem o módulo entre pip install sounddeviceno seu terminal.

Então, em seu script Python preferido (eu uso Juypter), digite

import sounddevice as sd

sd.play(audio, sr) vai tocar o que você quiser através do Python

A melhor maneira de obter o áudio e a taxa de amostragem que você deseja é com o módulo librosa. Digite isso no terminal se você não tiver o módulo librosa.

pip install librosa

audio, sr = librosa.load('wave_file.wav')

Seja qual for o arquivo wav que você deseja reproduzir, certifique-se de que esteja no mesmo diretório que o seu script Python. Isso deve permitir que você reproduza o arquivo wav desejado por meio do Python

Saúde, Charlie

PS

Uma vez que o áudio é um objeto de dados "librosa", o Python o vê como um array numpy. Como experiência, tente reproduzir uma coisa longa (tente 20.000 pontos de dados) de uma matriz numpy aleatória. Python deve interpretá-lo como ruído branco. O módulo de dispositivo de som também reproduz matrizes numpy e listas.

Charlie Carrera
fonte
fez isso, mas não está jogando nada. É só pular a chamada sd.play
Tobias Kolb
0

Em um notebook Colab, você pode fazer:

from IPython.display import Audio
Audio(waveform, Rate=16000)
Axel Bregnsbo
fonte
-1

Se você estiver no OSX, pode usar o módulo "os" ou "subprocesso" etc. para chamar o comando "play" do OSX. No shell do OSX, parece

toque "bah.wav"

Ele começa a tocar em cerca de meio segundo na minha máquina.

Moondoggy
fonte
1
Eu estaria interessado em ver a sintaxe de ambos os métodos.
MikeiLL
-1

Simplesmente, você pode fazer isso com a ajuda de cvlc- Fiz desta forma:

import os
os.popen2("cvlc /home/maulo/selfProject/task.mp3 --play-and-exit")

/home/maulo/selfProject/task.mp3. Este é o local do meu arquivo mp3. com a ajuda de "--play-and-exit" você poderá reproduzir o som novamente sem encerrar o processo de vlc.

pyAddict
fonte