Riproduci audio con Python


107

Come posso riprodurre l'audio (sarebbe come un suono di 1 secondo) da uno script Python?

Sarebbe meglio se fosse indipendente dalla piattaforma, ma prima deve funzionare su un Mac.

So che potrei semplicemente eseguire il afplay file.mp3comando dall'interno di Python, ma è possibile farlo in Python grezzo? Sarei anche meglio se non si basasse su librerie esterne.


Pyglet ha la capacità di riprodurre l'audio tramite una libreria esterna chiamata AVbin . Pyglet è un wrapper ctypes attorno alle chiamate di sistema native su ciascuna piattaforma che supporta. Sfortunatamente, non credo che nulla nella libreria standard riprodurrà l'audio.
tecnomalogico

Se hai bisogno di una libreria audio Python portatile, prova PyAudio . Sicuramente ha una porta per Mac. Per quanto riguarda i file mp3: è sicuramente fattibile in Python "grezzo", solo che temo che dovresti codificare tutto da solo :). Se puoi permetterti una libreria esterna, ho trovato alcuni esempi di PyAudio - PyLame qui.
Grzegorz Gacek

Risposte:



42

La soluzione migliore è probabilmente usare pygame / SDL . È una libreria esterna, ma ha un ottimo supporto su tutte le piattaforme.

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

Puoi trovare documentazione più specifica sul supporto del mixer audio nella documentazione di pygame.mixer.music


2
Per me, questo non funzionava. Voglio dire, stava suonando ma nessun suono. Ho aggiunto time.sleep(5)alla fine e ha funzionato. Python 3.6 su Windows 8.1
Nagabhushan SN

Pacchetto fuoco! Grazie!
Сергей Зеленчук

Non funziona su fedora con standard ".wav", ".mp3" e ".ogg" (Impossibile aprire il file 'filename.format')
Calvin-Ruiz

1
@ Calvin-Ruiz Ho appena confermato che sono in grado di utilizzare il codice sopra in FC31 per riprodurre file MP3 e Ogg. Penso che tu abbia un problema più grande che probabilmente richiede una conoscenza dettagliata della tua piattaforma.
TML

18

Dai un'occhiata a Simpleaudio , che è una libreria relativamente recente e leggera per questo scopo:

> pip install simpleaudio

Poi:

import simpleaudio as sa

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

Assicurati di utilizzare file PCM a 16 bit non compressi.


Bene, grazie - utile per i giochi che devono riprodurre brevi effetti sonori e supporta Python 3.
Thomas Perl

18

Prova playsound che è un Pure Python, multipiattaforma, modulo a funzione singola senza dipendenze per la riproduzione dei suoni.

Installa tramite pip:

$ pip install playsound

Una volta installato, puoi usarlo in questo modo:

from playsound import playsound
playsound('/path/to/a/sound/file/you/want/to/play.mp3')

36
Leggere questo mi ha reso così emozionante. I miei occhi letteralmente lacrimavano di felicità. Non mi aspettavo quel tipo di reazione da me stesso. (Si sono collegati a un modulo che ho creato.)
ArtOfWarfare

+1 per playsound. Ho appena provato un paio di soluzioni qui e questa ha funzionato nel modo più semplice per me. Purtroppo la pygamesoluzione non ha funzionato per me, durante un breve test.
Trevor Sullivan

13

In pydub abbiamo recentemente scelto di utilizzare ffplay (tramite sottoprocesso) dalla suite di strumenti ffmpeg, che internamente utilizza SDL.

Funziona per i nostri scopi, principalmente semplificando il test dei risultati del codice pydub in modalità interattiva, ma ha i suoi svantaggi, come far apparire un nuovo programma nel dock su Mac.

Ho collegato l'implementazione sopra, ma segue una versione semplificata:

import subprocess

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

Il -nodispflag impedisce a ffplay di mostrare una nuova finestra e il -autoexitflag fa uscire ffplay e restituisce un codice di stato al termine della riproduzione del file audio.

modifica : pydub ora usa pyaudio per la riproduzione quando è installato e torna a ffplay per evitare gli svantaggi che ho menzionato. Il collegamento sopra mostra anche questa implementazione.


1
Pydub sembra avere un bel po 'di potenziale come libreria wrapper: lo sto installando ora.
Shadow

1
Accidenti PyDub sembra carino ed è ancora molto attivo.
corysimmons

13

Ci scusiamo per la risposta tardiva, ma penso che questo sia un buon posto per pubblicizzare la mia libreria ...

Per quanto ne so, la libreria standard ha un solo modulo per riprodurre l'audio: ossaudiodev . Purtroppo, funziona solo su Linux e FreeBSD.

AGGIORNAMENTO: C'è anche winsound , ma ovviamente questo è anche specifico della piattaforma.

Per qualcosa di più indipendente dalla piattaforma, dovrai utilizzare una libreria esterna.

La mia raccomandazione è il modulo sounddevice (ma attenzione, sono l'autore).

Il pacchetto include la libreria PortAudio precompilata per Mac OS X e Windows e può essere facilmente installato con:

pip install sounddevice --user

Può riprodurre il suono dagli array NumPy, ma può anche usare semplici buffer Python (se NumPy non è disponibile).

Per riprodurre un array NumPy, è tutto ciò di cui hai bisogno (supponendo che i dati audio abbiano una frequenza di campionamento di 44100 Hz):

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

Per maggiori dettagli, dai un'occhiata alla documentazione .

Non può leggere / scrivere file audio, avrai bisogno di una libreria separata per questo.


Grande! Proprio quello che mi serviva per creare un programma dimostrativo di classe sulle onde.
Bill N


4

La risposta di Aaron sembra essere circa 10 volte più complicata del necessario. Basta farlo se hai solo bisogno di una risposta che funzioni su OS X:

from AppKit import NSSound

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

Una cosa ... questo ritorna immediatamente. Quindi potresti voler fare anche questo, se vuoi che la chiamata si blocchi fino al termine della riproduzione del suono.

from time import sleep

sleep(sound.duration())

Modifica: ho preso questa funzione e l'ho combinata con varianti per Windows e Linux. Il risultato è un puro Python, modulo multipiattaforma senza dipendenze chiamato playsound . L'ho caricato su pypi.

pip install playsound

Quindi eseguilo in questo modo:

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

I file MP3 funzionano anche su OS X. WAV dovrebbe funzionare su tutte le piattaforme. Non so quali altre combinazioni di piattaforma / formato di file facciano o non funzionino - non le ho ancora provate.


Ottengo il seguente errore: "Impossibile convertire l'oggetto 'byte' in str implicitamente" su Python 3.5 (Windows).
Erwin Mayer

@ErwinMayer - Stai parlando del playsoundmodulo che ho scritto? Non l'ho testato su qualcosa di più recente di Python 2.7.11 ... posso sicuramente cercare di risolverlo su 3.5 ...
ArtOfWarfare

Infatti. Deve essere dovuto alle differenze di Python 3.
Erwin Mayer

AppKit è una dipendenza.
Chris Larson

2
@ArtOfWarfare Semplicemente non è vero. Viene installato con il sistema python, ma non con la maggior parte delle distribuzioni, comprese le distribuzioni ufficiali di python.org. La maggior parte delle persone che conosco che usano python installano una delle distribuzioni per superare le restrizioni SIP. Per ottenere AppKit per la maggior parte delle distribuzioni, un utente deve installare pip pyobjc. Il che lo rende decisamente una dipendenza.
Chris Larson

3

Questo è il più semplice e il migliore che ho trovato. Supporta 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)

Vedi https://github.com/bastibe/PySoundFile e https://github.com/bastibe/SoundCard per tantissime altre funzioni super utili.


Solo un avvertimento per chiunque voglia fare questo (come lo sono io). Tutte le librerie e le loro dipendenze impiegano un'eternità per costruire su un Raspberry Pi 1B +, ​​in particolare numpy.
pojda

PS: questo non ha funzionato per raspberry pi "NotImplementedError: SoundCard non supporta ancora linux2", e non sono riuscito a trovare un modo per risolverlo. Vado con os.system ("mpg123 file.mp3")
pojda

Ah, fa schifo. Immagino che il lampone pi sia un ambiente un po 'speciale. Forse se hai pubblicato un problema su issuetracker potresti risolverlo o risolverlo.
n00p

Ripensandoci, forse il problema è che stai usando un vecchio kernel o una vecchia versione di Python. Con le versioni più recenti di Python quell'errore non dovrebbe assomigliare a quello che penso.
n00p

Funziona con Raspbian, che è fondamentalmente un fork di Debian Stretch. Mi sono arreso e sono andato nel modo os.system che funziona perfettamente atm. Grazie per avermi aiutato!
pojda

2

È possibile riprodurre l'audio in OS X senza alcuna libreria di terze parti utilizzando un analogo del codice seguente. I dati audio grezzi possono essere inseriti con wave_wave.writeframes. Questo codice estrae 4 secondi di audio dal file di input.

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()

Questo è molto più complicato del necessario: hanno chiesto come suonare semplicemente un suono, non come manipolarlo e poi suonarlo. La mia risposta elimina il 90% non necessario da questa risposta e lascia esattamente ciò che il richiedente voleva: riprodurre un suono da un file in OS X usando Python. stackoverflow.com/a/34984200/901641
ArtOfWarfare

2

Prova PySoundCard che utilizza PortAudio per la riproduzione, disponibile su molte piattaforme. Inoltre, riconosce i dispositivi audio "professionali" con molti canali.

Ecco un piccolo esempio dal file Readme:

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()

Sebbene interessanti, le risposte di solo collegamento sono scoraggiate. Come minimo, dovresti includere nella tua risposta un breve esempio di utilizzo. Ciò protegge anche la tua risposta dalla perdita di tutto il suo valore, nel caso in cui il repository venisse rinominato e il collegamento fosse sospeso.
spettri

2

Anche su OSX - da SO , utilizzando il comando afplay di OSX :

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

AGGIORNAMENTO: Tutto ciò che fa è specificare come fare ciò che l'OP voleva evitare di fare in primo luogo. Immagino di averlo pubblicato qui perché ciò che OP voleva evitare erano le informazioni che stavo cercando. Ops.


Funziona alla grande anche se mette in pausa l'esecuzione durante la riproduzione. Forse esiste un modo asincrono per chiamarlo?
Prassitele

Buone domande @Praxiteles. Possibilmente con la filettatura. vedi qui Per favore, riferisci se hai la possibilità di sperimentarlo.
MikeiLL

Il PO ha chiesto esplicitamente alternative a questo.
whitey04

L'OP è / stava cercando un'alternativa a "eseguire il comando afplay file.mp3 dall'interno di Python", e il sottoprocesso avviene ancora all'interno di Python, non è vero. Mi correggo. Ma probabilmente non fa male avere questo postino qui perché potrebbe aiutare gli altri.
MikeiLL

@ whitey04 Ho (finalmente) capito cosa stai dicendo.
MikeiLL

1

Pypi ha un elenco di moduli per Python nella musica. Il mio preferito sarebbe jython perché ha più risorse e librerie per la musica. Come esempio di codice per suonare una singola nota dal libro di testo :

# 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!

1

Mac OS Ho provato molti codici ma solo questo funziona su di me

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

1

Installa il playsoundpacchetto usando:

pip install playsound

Uso:

from playsound import playsound
playsound("file location\audio.p3")

0
Mettilo all'inizio dello script Python che stai scrivendo:
import subprocess
Se il file wav è nella directory dello script python:
f = './mySound.wav'
subprocess.Popen(['aplay','-q',f)
Se il file wav NON è nella directory dello script python:
f = 'mySound.wav'
subprocess.Popen(['aplay','-q', 'wav/' + f)
Se vuoi saperne di più su aplay:
man aplay

0

Per riprodurre un suono di notifica utilizzando Python, chiama un lettore musicale, come vlc. VLC mi ha chiesto di utilizzare la sua versione a riga di comando, cvlc, invece.

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

Richiede che vlc sia preinstallato sul dispositivo. Testato su Linux (Ubuntu 16.04 LTS); Esecuzione di Python 3.5.


0

Prova sounddevice

Se non hai il modulo entra pip install sounddevicenel tuo terminale.

Quindi nel tuo script Python preferito (io uso Juypter), inserisci

import sounddevice as sd

sd.play(audio, sr) giocherà quello che vuoi tramite Python

Il modo migliore per ottenere l'audio e il campionamento desiderati è con il modulo librosa. Inseriscilo nel terminale se non hai il modulo librosa.

pip install librosa

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

Qualunque sia il file wav che desideri riprodurre, assicurati che sia nella stessa directory del tuo script Python. Questo dovrebbe consentirti di riprodurre il file wav desiderato tramite Python

Salute, Charlie

PS

Una volta che l'audio è un oggetto dati "librosa", Python lo vede come un array numpy. Come esperimento, prova a riprodurre una cosa lunga (prova 20.000 punti dati) di un array numpy casuale. Python dovrebbe riprodurlo come rumore bianco. Il modulo sounddevice riproduce anche array ed elenchi numpy.


fatto questo, ma non sta riproducendo nulla. Sta solo saltando la chiamata a sd.play
Tobias Kolb

0

In un taccuino Colab puoi fare:

from IPython.display import Audio
Audio(waveform, Rate=16000)


-1

Se sei su OSX, puoi usare il modulo "os" o "subprocess" ecc. Per chiamare il comando OSX "play". Dalla shell OSX, sembra

riproduci "bah.wav"

Inizia a suonare in circa mezzo secondo sulla mia macchina.


1
Sarei interessato a vedere la sintassi per entrambi questi metodi.
MikeiLL

-1

Semplicemente puoi farlo con l'aiuto di cvlc- L'ho fatto in questo modo:

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

/home/maulo/selfProject/task.mp3. Questa è la posizione del mio file mp3. con l'aiuto di "--play-and-exit" sarai in grado di riprodurre di nuovo il suono senza terminare il processo vlc.

Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.