Spielen Sie Audio mit Python ab


107

Wie kann ich Audio (es wäre wie ein 1-Sekunden-Sound) aus einem Python-Skript abspielen?

Es wäre am besten, wenn es plattformunabhängig wäre, aber zuerst muss es auf einem Mac funktionieren.

Ich weiß, dass ich den afplay file.mp3Befehl nur in Python ausführen kann , aber ist es möglich, ihn in rohem Python auszuführen ? Ich wäre auch besser, wenn es nicht auf externe Bibliotheken angewiesen wäre.


Pyglet kann Audio über eine externe Bibliothek namens AVbin wiedergeben . Pyglet ist ein ctypes-Wrapper für native Systemaufrufe auf jeder unterstützten Plattform. Leider glaube ich nicht, dass irgendetwas in der Standardbibliothek Audio wiedergeben wird.
Technomalogical

Wenn Sie eine tragbare Python- Audiobibliothek benötigen, versuchen Sie es mit PyAudio . Es hat sicherlich einen Mac-Port. Was MP3-Dateien betrifft: Es ist sicherlich in "rohem" Python machbar, nur ich fürchte, Sie müssten alles selbst codieren :). Wenn Sie sich eine externe Bibliothek leisten können, habe ich hier ein PyAudio - PyLame - Beispiel gefunden.
Grzegorz Gacek

Antworten:



42

Am besten verwenden Sie wahrscheinlich Pygame / SDL . Es ist eine externe Bibliothek, die jedoch plattformübergreifend großartige Unterstützung bietet.

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

Eine genauere Dokumentation zur Unterstützung von Audiomischern finden Sie in der Dokumentation zu pygame.mixer.music


2
Für mich hat das nicht funktioniert. Ich meine, es wurde gespielt, aber kein Ton. Ich habe time.sleep(5)am Ende hinzugefügt und das hat funktioniert. Python 3.6 unter Windows 8.1
Nagabhushan SN

Feuerpaket! Vielen Dank!
11ергей Зеленчук

Es funktioniert nicht auf Fedora mit Standard ".wav", ".mp3" und ".ogg" (Datei 'filename.format' kann nicht geöffnet werden)
Calvin-Ruiz

1
@ Calvin-Ruiz Ich habe gerade bestätigt, dass ich den obigen Code in FC31 zum Abspielen von MP3- und Ogg-Dateien verwenden kann. Ich denke, Sie haben ein größeres Problem, das wahrscheinlich einige detaillierte Kenntnisse Ihrer Plattform erfordert.
TML

18

Schauen Sie sich Simpleaudio an , eine relativ neue und leichtgewichtige Bibliothek für diesen Zweck:

> pip install simpleaudio

Dann:

import simpleaudio as sa

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

Stellen Sie sicher, dass Sie unkomprimierte 16-Bit-PCM-Dateien verwenden.


Schön, danke - nützlich für Spiele, die kurze Soundeffekte spielen müssen, und unterstützt Python 3.
Thomas Perl

18

Probieren Sie PlaySound aus , einen plattformübergreifenden Pure Python-Einzelfunktionsbaustein ohne Abhängigkeiten für das Abspielen von Sounds.

Installation über Pip:

$ pip install playsound

Sobald Sie installiert haben, können Sie es wie folgt verwenden:

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

36
Das zu lesen machte mich so emotional. Meine Augen waren buchstäblich vor Glück zerfetzt. Ich habe diese Art von Reaktion nicht von mir erwartet. (Sie sind mit einem Modul verknüpft, das ich erstellt habe.)
ArtOfWarfare

+1 für playsound. Ich habe hier gerade ein paar Lösungen getestet, und diese hat für mich am einfachsten funktioniert. Leider hat die pygameLösung bei einem kurzen Test bei mir nicht funktioniert.
Trevor Sullivan

13

In pydub haben wir uns kürzlich für die Verwendung von ffplay (über einen Unterprozess) aus der ffmpeg- Tool- Suite entschieden, die intern SDL verwendet.

Es funktioniert für unsere Zwecke - hauptsächlich, um das Testen der Ergebnisse von Pydub-Code im interaktiven Modus zu vereinfachen -, hat jedoch auch Nachteile, z. B. das Erscheinen eines neuen Programms im Dock auf dem Mac.

Ich habe die Implementierung oben verlinkt, aber es folgt eine vereinfachte Version:

import subprocess

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

Das -nodispFlag verhindert, dass ffplay ein neues Fenster anzeigt, und das -autoexitFlag bewirkt, dass ffplay beendet wird und einen Statuscode zurückgibt, wenn die Audiodatei abgespielt ist.

edit : pydub verwendet jetzt pyaudio für die Wiedergabe, wenn es installiert ist, und greift auf ffplay zurück, um die von mir erwähnten Nachteile zu vermeiden. Der obige Link zeigt auch diese Implementierung.


1
Pydub sieht so aus, als hätte es einiges Potenzial als Wrapper-Bibliothek - ich installiere es jetzt.
Schatten

1
Verdammt PyDub sieht gut aus und ist immer noch sehr aktiv.
Corysimmons

13

Entschuldigen Sie die späte Antwort, aber ich denke, dies ist ein guter Ort, um für meine Bibliothek zu werben ...

AFAIK, die Standardbibliothek, hat nur ein Modul für die Audiowiedergabe: ossaudiodev . Leider funktioniert dies nur unter Linux und FreeBSD.

UPDATE: Es gibt auch Winsound , aber dies ist natürlich auch plattformspezifisch.

Für etwas plattformunabhängigeres müssen Sie eine externe Bibliothek verwenden.

Meine Empfehlung ist das Soundgeräte- Modul (aber Vorsicht, ich bin der Autor).

Das Paket enthält die vorkompilierte PortAudio- Bibliothek für Mac OS X und Windows und kann einfach installiert werden mit:

pip install sounddevice --user

Es kann Sound von NumPy-Arrays wiedergeben, aber es können auch einfache Python-Puffer verwendet werden (wenn NumPy nicht verfügbar ist).

Um ein NumPy-Array wiederzugeben, ist dies alles, was Sie benötigen (vorausgesetzt, die Audiodaten haben eine Abtastfrequenz von 44100 Hz):

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

Weitere Informationen finden Sie in der Dokumentation .

Es kann keine Audiodateien lesen / schreiben, dafür benötigen Sie eine separate Bibliothek.


Toll! Genau das, was ich brauchte, um ein Klassendemo-Programm über Wellen zu erstellen.
Bill N


4

Aarons Antwort scheint etwa zehnmal komplizierter als nötig zu sein. Tun Sie dies einfach, wenn Sie nur eine Antwort benötigen, die unter OS X funktioniert:

from AppKit import NSSound

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

Eine Sache ... das kehrt sofort zurück. Möglicherweise möchten Sie dies auch tun, wenn der Anruf blockiert werden soll, bis die Wiedergabe des Sounds beendet ist.

from time import sleep

sleep(sound.duration())

Bearbeiten: Ich habe diese Funktion übernommen und mit Varianten für Windows und Linux kombiniert. Das Ergebnis ist ein plattformübergreifendes reines Python-Modul ohne Abhängigkeiten, das als PlaySound bezeichnet wird . Ich habe es auf pypi hochgeladen.

pip install playsound

Führen Sie es dann folgendermaßen aus:

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

MP3-Dateien funktionieren auch unter OS X. WAV sollte auf allen Plattformen funktionieren. Ich weiß nicht, welche anderen Kombinationen von Plattform- / Dateiformat funktionieren oder nicht - ich habe sie noch nicht ausprobiert.


Ich erhalte die folgende Fehlermeldung: "Das Byte-Objekt kann nicht implizit in str konvertiert werden" unter Python 3.5 (Windows).
Erwin Mayer

@ErwinMayer - Sprechen Sie über das playsoundModul, das ich geschrieben habe? Ich habe es auf nichts Neuerem als Python 2.7.11 getestet ... Ich kann mir sicher ansehen, wie ich es auf 3.5
beheben kann

Tatsächlich. Dies muss auf Python 3-Unterschiede zurückzuführen sein.
Erwin Mayer

AppKit ist eine Abhängigkeit.
Chris Larson

2
@ArtOfWarfare Das stimmt einfach nicht . Es wird mit dem Systempython installiert, jedoch nicht mit den meisten Distributionen, einschließlich der offiziellen Distributionen von python.org. Die meisten Leute, die Python kennen, installieren eine der Distributionen, um die SIP-Einschränkungen zu überwinden. Um AppKit für die meisten Distributionen zu erhalten, muss ein Benutzer pyobjc per Pip installieren. Was es definitiv zu einer Abhängigkeit macht.
Chris Larson

3

Dies ist die einfachste und beste, die ich gefunden habe. Es unterstützt Linux / pulseaudio, Mac / coreaudio und 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)

Unter https://github.com/bastibe/PySoundFile und https://github.com/bastibe/SoundCard finden Sie unzählige weitere nützliche Funktionen.


Nur ein Headsup für alle, die sich dafür entscheiden (so wie ich). Es dauert ewig, bis alle Bibliotheken und ihre Abhängigkeiten auf einem Raspberry Pi 1B + aufbauen - besonders numpy.
Pojda

PS: Dies funktionierte nicht für Himbeer-Pi "NotImplementedError: SoundCard unterstützt Linux2 noch nicht" und konnte keinen Weg finden, dies zu beheben. Ich gehe mit os.system ("mpg123 file.mp3")
pojda

Ah, das ist scheiße. Ich denke, Himbeer-Pi ist eine etwas besondere Umgebung. Wenn Sie ein Problem im Issuetracker gepostet haben, können Sie es möglicherweise aussortieren oder beheben.
n00p

Bei weiteren Überlegungen besteht das Problem möglicherweise darin, dass Sie einen alten Kernel oder eine alte Python-Version verwenden. Bei neueren Python-Versionen sollte dieser Fehler meiner Meinung nach nicht so aussehen.
n00p

Es läuft Raspbian, was im Grunde eine Debian Stretch Gabel ist. Ich gab auf und ging den os.system Weg, der gut funktioniert atm. Danke, dass du mir geholfen hast!
Pojda

2

Es ist möglich, Audio in OS X ohne Bibliotheken von Drittanbietern mit einem Analogon des folgenden Codes abzuspielen. Die rohen Audiodaten können mit wave_wave.writeframes eingegeben werden. Dieser Code extrahiert 4 Sekunden Audio aus der Eingabedatei.

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

Dies ist weitaus komplizierter als nötig - sie fragten, wie man einfach einen Sound spielt, nicht wie man ihn manipuliert und dann spielt. Meine Antwort schneidet die unnötigen 90% dieser Antwort ab und lässt genau das, was der Fragesteller wollte - das Abspielen eines Sounds aus einer Datei in OS X mit Python. stackoverflow.com/a/34984200/901641
ArtOfWarfare

2

Probieren Sie PySoundCard aus, die PortAudio für die Wiedergabe verwendet, die auf vielen Plattformen verfügbar ist. Darüber hinaus erkennt es "professionelle" Audiogeräte mit vielen Kanälen.

Hier ein kleines Beispiel aus der 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()

Obwohl interessant, wird von Antworten nur mit Links abgeraten. Sie sollten mindestens ein kurzes Beispiel für die Verwendung in Ihre Antwort aufnehmen. Dies schützt Ihre Antwort auch davor, ihren gesamten Wert zu verlieren, falls das Repository umbenannt wird und der Link baumelt.
Spektren

2

Auch unter OSX - von SO aus mit dem afplay- Befehl afplay :

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

UPDATE: Alles, was dies tut, ist anzugeben, wie das zu tun ist, was das OP überhaupt vermeiden wollte. Ich schätze, ich habe dies hier gepostet, weil OP die Informationen vermeiden wollte, nach denen ich gesucht habe. Hoppla.


Funktioniert hervorragend, pausiert jedoch die Ausführung, während es abgespielt wird. Vielleicht gibt es eine asynchrone Möglichkeit, dies zu nennen?
Praxiteles

Gute Fragen @Praxiteles. Möglicherweise mit Einfädeln. siehe hier Bitte melden Sie sich zurück, wenn Sie die Möglichkeit haben, damit zu experimentieren.
MikeiLL

Das OP hat ausdrücklich nach Alternativen dazu gefragt.
whitey04

Das OP ist / war auf der Suche nach einer Alternative zum "Ausführen des Befehls afplay file.mp3 in Python", und die Unterverarbeitung findet immer noch in Python statt, nicht wahr? Ich stehe korrigiert. Aber es tut wahrscheinlich nicht weh, diesen kleinen Beitrag hier zu haben, da er anderen helfen kann.
MikeiLL

@ whitey04 Ich sehe (endlich) was du sagst.
MikeiLL

1

Pypi hat eine Liste von Modulen für Python in der Musik. Mein Favorit wäre Jython, weil es mehr Ressourcen und Bibliotheken für Musik hat. Als Beispiel für Code zum Abspielen einer einzelnen Note aus dem Lehrbuch :

# 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 Ich habe viele Codes ausprobiert, aber genau das funktioniert bei mir

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

Installieren Sie das playsoundPaket mit:

pip install playsound

Verwendung:

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

0
Fügen Sie dies oben in Ihr Python-Skript ein, das Sie schreiben:
import subprocess
Wenn sich die WAV-Datei im Verzeichnis des Python-Skripts befindet:
f = './mySound.wav'
subprocess.Popen(['aplay','-q',f)
Wenn sich die WAV-Datei NICHT im Verzeichnis des Python-Skripts befindet:
f = 'mySound.wav'
subprocess.Popen(['aplay','-q', 'wav/' + f)
Wenn Sie mehr über aplay erfahren möchten:
man aplay

0

Rufen Sie einen Musikplayer wie vlc auf, um einen Benachrichtigungston mit Python abzuspielen. VLC forderte mich auf, stattdessen die Befehlszeilenversion cvlc zu verwenden.

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

Vlc muss auf dem Gerät vorinstalliert sein. Getestet unter Linux (Ubuntu 16.04 LTS); Ausführen von Python 3.5.


0

Versuchen Sie es mit Soundgerät

Wenn Sie das Modul nicht haben, geben Sie es pip install sounddevicein Ihr Terminal ein.

Geben Sie dann in Ihrem bevorzugten Python-Skript (ich verwende Juypter) ein

import sounddevice as sd

sd.play(audio, sr) wird über Python spielen, was Sie wollen

Der beste Weg, um das gewünschte Audio und Samplerate zu erhalten, ist das librosa-Modul. Geben Sie dies im Terminal ein, wenn Sie nicht über das librosa-Modul verfügen.

pip install librosa

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

Unabhängig davon, welche WAV-Datei Sie abspielen möchten, stellen Sie sicher, dass sie sich im selben Verzeichnis wie Ihr Python-Skript befindet. Dies sollte es Ihnen ermöglichen, Ihre gewünschte WAV-Datei über Python abzuspielen

Prost, Charlie

PS

Sobald Audio ein "librosa" -Datenobjekt ist, sieht Python es als numpy-Array. Versuchen Sie als Experiment, ein langes (versuchen Sie 20.000 Datenpunkte) Ding eines zufälligen Numpy-Arrays zu spielen. Python sollte es als weißes Rauschen spielen. Das Sounddevice-Modul spielt auch numpy Arrays und Listen ab.


habe das getan, aber es spielt nichts. Es wird nur der sd.play-Anruf übersprungen
Tobias Kolb

0

In einem Colab-Notizbuch können Sie Folgendes tun:

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


-1

Wenn Sie unter OSX arbeiten, können Sie mit dem Modul "os" oder "subprocess" usw. den OSX-Befehl "play" aufrufen. In der OSX-Shell sieht es so aus

spiele "bah.wav"

Es beginnt in ungefähr einer halben Sekunde auf meinem Computer zu spielen.


1
Es würde mich interessieren, die Syntax für beide Methoden zu sehen.
MikeiLL

-1

Einfach Sie können es mit Hilfe von cvlc tun - ich habe es so gemacht:

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

/home/maulo/selfProject/task.mp3. Dies ist der Speicherort meiner MP3-Datei. Mit Hilfe von "--play-and-exit" können Sie den Sound erneut abspielen, ohne den vlc-Prozess zu beenden.

Durch die Nutzung unserer Website bestätigen Sie, dass Sie unsere Cookie-Richtlinie und Datenschutzrichtlinie gelesen und verstanden haben.
Licensed under cc by-sa 3.0 with attribution required.