Écouter de l'audio avec Python


107

Comment puis-je lire de l'audio (ce serait comme un son d'une seconde) à partir d'un script Python?

Ce serait mieux s'il était indépendant de la plate-forme, mais il doit d'abord fonctionner sur un Mac.

Je sais que je pourrais simplement exécuter la afplay file.mp3commande à partir de Python, mais est-il possible de le faire en Python brut? Je serais également mieux s'il ne reposait pas sur des bibliothèques externes.


Pyglet a la capacité de lire de l'audio via une bibliothèque externe appelée AVbin . Pyglet est un wrapper ctypes autour des appels système natifs sur chaque plateforme qu'il prend en charge. Malheureusement, je ne pense pas que quoi que ce soit dans la bibliothèque standard puisse lire de l'audio.
technomalogical

Si vous avez besoin d'une bibliothèque audio Python portable, essayez PyAudio . Il a certainement un port mac. En ce qui concerne les fichiers mp3: c'est certainement faisable en Python "brut", mais j'ai peur que vous deviez tout coder vous-même :). Si vous pouvez vous permettre une bibliothèque externe, j'ai trouvé un échantillon PyAudio - PyLame ici.
Grzegorz Gacek

Réponses:



42

Votre meilleur pari est probablement d'utiliser pygame / SDL . C'est une bibliothèque externe, mais elle offre un excellent support sur toutes les plates-formes.

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

Vous pouvez trouver une documentation plus spécifique sur la prise en charge du mixeur audio dans la documentation de pygame.mixer.music


2
Pour moi, cela ne fonctionnait pas. Je veux dire, il jouait mais pas de son. J'ai ajouté time.sleep(5)à la fin et cela a fonctionné. Python 3.6 sur Windows 8.1
Nagabhushan SN

Paquet de feu! Merci!
Сергей Зеленчук

Cela ne fonctionne pas sur fedora avec les standards ".wav", ".mp3" et ".ogg" (Impossible d'ouvrir le fichier 'filename.format')
Calvin-Ruiz

1
@ Calvin-Ruiz Je viens de confirmer que je suis capable d'utiliser le code ci-dessus dans FC31 pour lire des fichiers MP3 et Ogg. Je pense que vous avez un problème plus vaste qui nécessite probablement une connaissance détaillée de votre plate-forme.
TML

18

Jetez un œil à Simpleaudio , qui est une bibliothèque relativement récente et légère à cet effet:

> pip install simpleaudio

Ensuite:

import simpleaudio as sa

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

Assurez-vous d'utiliser des fichiers PCM 16 bits non compressés.


Bien, merci - utile pour les jeux qui doivent jouer des effets sonores courts et prend en charge Python 3.
Thomas Perl

18

Essayez playound qui est un module de fonction unique, multi-plateforme, Pure Python, sans dépendances pour la lecture de sons.

Installer via pip:

$ pip install playsound

Une fois que vous avez installé, vous pouvez l'utiliser comme ceci:

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

36
La lecture de ceci m'a rendu si émouvant. Mes yeux se sont littéralement déchirés de bonheur. Je ne m'attendais pas à ce genre de réaction de ma part. (Ils ont lié à un module que j'ai créé.)
ArtOfWarfare

+1 pour playsound. Je viens de tester quelques solutions ici, et celle-ci a fonctionné le plus facilement pour moi. Malheureusement, la pygamesolution n'a pas fonctionné pour moi, lors d'un bref test.
Trevor Sullivan

13

Dans pydub, nous avons récemment choisi d'utiliser ffplay (via un sous-processus) de la suite d'outils ffmpeg, qui utilise en interne SDL.

Cela fonctionne pour nos besoins - principalement en facilitant le test des résultats du code pydub en mode interactif - mais il a ses inconvénients, comme faire apparaître un nouveau programme dans le dock sur mac.

J'ai lié l'implémentation ci-dessus, mais une version simplifiée suit:

import subprocess

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

L' -nodispindicateur empêche ffplay d'afficher une nouvelle fenêtre, et l' -autoexitindicateur fait quitter ffplay et renvoie un code d'état lorsque la lecture du fichier audio est terminée.

edit : pydub utilise maintenant pyaudio pour la lecture lorsqu'il est installé et revient à ffplay pour éviter les inconvénients que j'ai mentionnés. Le lien ci-dessus montre également cette mise en œuvre.


1
Pydub semble avoir beaucoup de potentiel en tant que bibliothèque de wrapper - je l'installe maintenant.
Shadow

1
Damn PyDub est beau et il est toujours très actif.
corysimmons

13

Désolé pour la réponse tardive, mais je pense que c'est un bon endroit pour annoncer ma bibliothèque ...

AFAIK, la bibliothèque standard ne possède qu'un seul module de lecture audio: ossaudiodev . Malheureusement, cela ne fonctionne que sur Linux et FreeBSD.

MISE À JOUR: Il y a aussi winsound , mais évidemment c'est aussi spécifique à la plate-forme.

Pour quelque chose de plus indépendant de la plate-forme, vous devrez utiliser une bibliothèque externe.

Ma recommandation est le module sounddevice (mais attention, je suis l'auteur).

Le package comprend la bibliothèque PortAudio pré-compilée pour Mac OS X et Windows, et peut être facilement installé avec:

pip install sounddevice --user

Il peut lire le son des tableaux NumPy, mais il peut également utiliser des tampons Python simples (si NumPy n'est pas disponible).

Pour lire un tableau NumPy, c'est tout ce dont vous avez besoin (en supposant que les données audio ont une fréquence d'échantillonnage de 44100 Hz):

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

Pour plus de détails, consultez la documentation .

Il ne peut pas lire / écrire des fichiers audio, vous aurez besoin d'une bibliothèque séparée pour cela.


Génial! Juste ce dont j'avais besoin pour créer un programme de démonstration sur les ondes.
Bill N


4

La réponse d'Aaron semble être environ 10 fois plus compliquée que nécessaire. Faites-le simplement si vous n'avez besoin que d'une réponse qui fonctionne sous OS X:

from AppKit import NSSound

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

Une chose ... cela revient immédiatement. Vous pouvez donc également le faire si vous souhaitez que l'appel soit bloqué jusqu'à la fin de la lecture du son.

from time import sleep

sleep(sound.duration())

Edit: J'ai pris cette fonction et l'ai combinée avec des variantes pour Windows et Linux. Le résultat est un module multi-plateforme purement python sans dépendances appelé playound . Je l'ai téléchargé sur pypi.

pip install playsound

Puis exécutez-le comme ceci:

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

Les fichiers MP3 fonctionnent également sous OS X. WAV devrait fonctionner sur toutes les plates-formes. Je ne sais pas quelles autres combinaisons de plate-forme / format de fichier fonctionnent ou ne fonctionnent pas - je ne les ai pas encore essayées.


J'obtiens l'erreur suivante: "Impossible de convertir l'objet 'bytes' en str implicitement" sur Python 3.5 (Windows).
Erwin Mayer

@ErwinMayer - Parlez-vous du playsoundmodule que j'ai écrit? Je ne l'ai pas testé sur quelque chose de plus récent que Python 2.7.11 ... Je peux certainement chercher à résoudre ce
problème

En effet. Cela doit être dû aux différences de Python 3.
Erwin Mayer

AppKit est une dépendance.
Chris Larson

2
@ArtOfWarfare Ce n'est tout simplement pas vrai. Il est installé avec le système python, mais pas avec la plupart des distributions, y compris les distributions officielles de python.org. La plupart des gens que je connais qui utilisent python installent l'une des distributions pour contourner les restrictions SIP. Pour obtenir AppKit pour la plupart des distributions, un utilisateur doit installer pyobjc. Ce qui en fait certainement une dépendance.
Chris Larson

3

C'est la meilleure et la plus facile à trouver. Il prend en charge Linux / pulseaudio, Mac / coreaudio et 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)

Voir https://github.com/bastibe/PySoundFile et https://github.com/bastibe/SoundCard pour des tonnes d'autres fonctionnalités super utiles.


Juste un avertissement pour tous ceux qui y vont (comme je le suis). Toutes les bibliothèques et leurs dépendances mettent une éternité à se construire sur un Raspberry Pi 1B + - en particulier numpy.
pojda

PS: cela n'a pas fonctionné pour raspberry pi "NotImplementedError: SoundCard ne supporte pas encore linux2", et n'a pas pu trouver un moyen de le réparer. Je vais avec os.system ("mpg123 file.mp3")
pojda

Ah, ça craint. Je suppose que le Raspberry Pi est un environnement un peu spécial. Peut-être que si vous publiez un problème sur le Issueetracker, vous pourriez le résoudre ou le résoudre.
n00p

Après réflexion, le problème est peut-être que vous utilisez un ancien noyau ou une ancienne version de python. Avec les nouvelles versions de Python, cette erreur ne devrait pas ressembler à cela, je pense.
n00p

Il exécute Raspbian, qui est essentiellement un fork de Debian Stretch. J'ai abandonné et suis allé à la manière os.system qui fonctionne très bien atm. Merci pour votre aide!
pojda

2

Il est possible de lire de l'audio sous OS X sans aucune bibliothèque tierce en utilisant un analogue du code suivant. Les données audio brutes peuvent être entrées avec wave_wave.writeframes. Ce code extrait 4 secondes d'audio du fichier d'entrée.

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

C'est beaucoup plus compliqué que nécessaire - ils ont demandé comment jouer simplement un son, pas comment le manipuler puis le jouer. Ma réponse supprime les 90% inutiles de cette réponse et laisse exactement ce que le demandeur voulait: jouer un son à partir d'un fichier sous OS X en utilisant Python. stackoverflow.com/a/34984200/901641
ArtOfWarfare

2

Essayez PySoundCard qui utilise PortAudio pour la lecture, disponible sur de nombreuses plates-formes. De plus, il reconnaît les appareils audio "professionnels" avec de nombreux canaux.

Voici un petit exemple du 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()

Bien qu'intéressantes, les réponses par lien uniquement sont déconseillées. Au minimum, vous devriez inclure dans votre réponse un court exemple d'utilisation. Cela empêche également votre réponse de perdre toute sa valeur, si le référentiel est renommé et que le lien devient suspendu.
spectres

2

Aussi sur OSX - depuis SO , en utilisant la commande afplay d'OSX :

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

MISE À JOUR: Tout cela ne fait que spécifier comment faire ce que l'OP voulait éviter de faire en premier lieu. Je suppose que j'ai posté ceci ici parce que ce que OP voulait éviter était l'information que je recherchais. Oups.


Fonctionne très bien mais met en pause l'exécution pendant la lecture. Peut-être existe-t-il un moyen asynchrone d'appeler cela?
Praxiteles le

Bonnes questions @Praxiteles. Éventuellement avec filetage. voir ici Veuillez faire un rapport si vous avez une chance de l'expérimenter.
MikeiLL

Le PO a explicitement demandé des alternatives à cela.
whitey04

L'OP cherche / cherchait une alternative pour "exécuter la commande afplay file.mp3 depuis Python", et le sous-traitement se produit toujours dans Python, n'est-ce pas. Je me suis trompé. Mais cela ne fait probablement pas de mal d'avoir ce petit message ici car cela peut aider les autres.
MikeiLL

@ whitey04 Je vois (enfin) ce que vous dites.
MikeiLL

1

Pypi a une liste de modules pour python dans la musique. Mon préféré serait jython car il a plus de ressources et de bibliothèques pour la musique. Comme exemple de code pour jouer une seule note du manuel :

# 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 j'ai essayé beaucoup de codes mais cela fonctionne sur moi

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

Installez le playsoundpackage en utilisant:

pip install playsound

Usage:

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

0
Mettez ceci en haut de votre script python que vous écrivez:
import subprocess
Si le fichier wav est dans le répertoire du script python:
f = './mySound.wav'
subprocess.Popen(['aplay','-q',f)
Si le fichier wav N'EST PAS dans le répertoire du script python:
f = 'mySound.wav'
subprocess.Popen(['aplay','-q', 'wav/' + f)
Si vous souhaitez en savoir plus sur aplay:
man aplay

0

Pour lire un son de notification à l'aide de python, appelez un lecteur de musique, tel que vlc. VLC m'a invité à utiliser sa version en ligne de commande, cvlc, à la place.

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

Il nécessite que vlc soit préinstallé sur l'appareil. Testé sous Linux (Ubuntu 16.04 LTS); Exécution de Python 3.5.


0

Essayez sounddevice

Si vous n'avez pas le module, entrez pip install sounddevicedans votre terminal.

Ensuite, dans votre script Python préféré (j'utilise Juypter), entrez

import sounddevice as sd

sd.play(audio, sr) jouera ce que vous voulez via Python

La meilleure façon d'obtenir l'audio et l'échantillonnage que vous souhaitez est d'utiliser le module librosa. Entrez ceci dans le terminal si vous n'avez pas le module librosa.

pip install librosa

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

Quel que soit le fichier wav que vous souhaitez lire, assurez-vous simplement qu'il se trouve dans le même répertoire que votre script Python. Cela devrait vous permettre de lire le fichier wav souhaité via Python

A bientôt, Charlie

PS

Une fois que l'audio est un objet de données "librosa", Python le voit comme un tableau numpy. À titre expérimental, essayez de jouer un long (essayez 20 000 points de données) d'un tableau numérique aléatoire. Python devrait le jouer comme du bruit blanc. Le module sounddevice lit également des tableaux et des listes numpy.


fait cela, mais il ne joue rien. Il suffit de sauter l'appel sd.play
Tobias Kolb

0

Dans un notebook Colab, vous pouvez faire:

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


-1

Si vous êtes sous OSX, vous pouvez utiliser le module "os" ou "sous-processus" etc. pour appeler la commande "play" OSX. Depuis le shell OSX, il ressemble à

jouer "bah.wav"

Il commence à jouer dans environ une demi-seconde sur ma machine.


1
Je serais intéressé de voir la syntaxe de ces deux méthodes.
MikeiLL

-1

Simplement, vous pouvez le faire avec l'aide de cvlc - je l'ai fait de cette façon:

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

/home/maulo/selfProject/task.mp3. C'est l'emplacement de mon fichier mp3. avec l'aide de "--play-and-exit", vous pourrez rejouer le son sans terminer le processus vlc.

En utilisant notre site, vous reconnaissez avoir lu et compris notre politique liée aux cookies et notre politique de confidentialité.
Licensed under cc by-sa 3.0 with attribution required.