Audio-Loops mit Python und Pydub: Wiederholen und Überblenden
Nutzen Sie harte Wiederholungen für exakte Kopien eines Clips oder überblenden Sie sein Ende und seinen Anfang, um einen abrupten Übergang abzumildern. Diese Anleitung erstellt mit Pydub eine WAV-Datei mit begrenzter Dauer, meldet Fehler über den Exit-Status und ersetzt keine vorhandene Ausgabedatei. Eine Überblendung kann ein Knacken reduzieren; sie garantiert keinen musikalisch nahtlosen Loop.
Voraussetzungen
Die Befehle verwenden Bash unter Linux, Python mit Unterstützung für virtuelle Umgebungen, FFmpeg und ffprobe. Die Anleitung wurde mit Python 3.12.13 und 3.14.7, Pydub 0.25.1 sowie FFmpeg 7.1.5 und 9.0.1 getestet. Installieren Sie Python und die nativen Werkzeuge über Ihre Distribution; die FFmpeg-Downloadseite verlinkt passende Pakete. Prüfen Sie die ausführbaren Programme:
python3 --version && ffmpeg -version && ffprobe -version
Verwenden Sie unkomprimierte WAV-Eingabedateien mit vorzeichenbehaftetem 16-Bit-PCM im Little-Endian-Format und einem oder zwei Kanälen. Das Skript behält Abtastrate und Kanäle bei und weist andere Sample-Formate zurück, statt deren Bytes als 16-Bit-Ganzzahlen zu interpretieren. Es baut das gesamte Ergebnis im Arbeitsspeicher auf. Beginnen Sie daher mit kurzen Clips.
Grundlegende Werkzeuge einrichten
Öffnen Sie eine Bash-Shell in einem neuen, leeren Arbeitsverzeichnis. Installieren Sie die Pakete
mit festgelegten Versionen in einer neuen virtuellen Umgebung. Die erste Prüfung verhindert die
Wiederverwendung einer vorhandenen Umgebung unter .venv:
test ! -e .venv && test ! -L .venv &&
python3 -m venv .venv &&
.venv/bin/python -m pip install 'pydub==0.25.1' 'audioop-lts==0.2.2; python_version >= "3.13"'
Python hat audioop in 3.13 entfernt. Pydub 0.25.1
verwendet es, daher stellt die bedingte Abhängigkeit
audioop-lts für neuere Python-Versionen bereit.
Diese Befehle nutzen die virtuelle Umgebung direkt; eine Aktivierung ist nicht nötig. Schlägt die
Installation fehl, bleibt die Shell in Ihrem Arbeitsverzeichnis. Wählen Sie ein neues Verzeichnis,
bevor Sie die Einrichtung erneut versuchen.
Einfache Loops mit Pydub
Speichern Sie dieses vollständige Programm als loop_audio.py. Der
Reader wave aus der Standardbibliothek
validiert den PCM-Container. Das Skript prüft, ob alle deklarierten Frames vorhanden sind, bevor es
ein Pydub-Segment erstellt. Es weist leere Dateien, Wiederholungszahlen kleiner oder gleich null,
negative Überblendungsdauern und Überblendungen von der Länge des Clips zurück.
Die Ausgabe wird neben ihrem Ziel zwischengespeichert und mit einem Hardlink veröffentlicht. Verwenden Sie ein beschreibbares lokales Dateisystem, das Hardlinks unterstützt, und ein vorhandenes Ausgabeverzeichnis. Bei einem regulären Fehler wird das temporäre Verzeichnis entfernt; eine vorhandene Zieldatei bleibt erhalten.
import argparse
import os
from pathlib import Path
import sys
from tempfile import TemporaryDirectory
import wave
from pydub import AudioSegment
def read_pcm(source):
with wave.open(str(source), 'rb') as recording:
channels = recording.getnchannels()
rate = recording.getframerate()
frames = recording.getnframes()
if (recording.getcomptype() != 'NONE'
or recording.getsampwidth() != 2 or channels not in (1, 2)):
raise ValueError('Expected mono or stereo signed 16-bit PCM WAV')
data = recording.readframes(frames)
if frames == 0 or len(data) != frames * channels * 2:
raise ValueError('Empty or truncated PCM data')
return AudioSegment(data=data, sample_width=2, frame_rate=rate, channels=channels)
def main():
parser = argparse.ArgumentParser(description='Repeat a PCM WAV clip')
parser.add_argument('--repeats', type=int, default=3)
parser.add_argument('--crossfade-ms', type=int, default=0)
parser.add_argument('input', type=Path)
parser.add_argument('output', type=Path)
args = parser.parse_args()
if args.repeats < 1 or args.crossfade_ms < 0:
parser.error('--repeats must be positive; --crossfade-ms must be nonnegative')
try:
if args.output.suffix.lower() != '.wav':
raise ValueError('The output must have a .wav extension')
if os.path.lexists(args.output):
raise FileExistsError(f'Output already exists: {args.output}')
audio = read_pcm(args.input)
if args.crossfade_ms and args.crossfade_ms >= len(audio):
raise ValueError('The crossfade must be shorter than the clip')
if args.crossfade_ms == 0:
combined = audio * args.repeats
else:
combined = audio
for _ in range(args.repeats - 1):
combined = combined.append(audio, crossfade=args.crossfade_ms)
with TemporaryDirectory(prefix='.loop-', dir=args.output.parent) as work:
staged = Path(work) / 'loop.wav'
combined.export(staged, format='wav').close()
os.link(staged, args.output)
except (OSError, ValueError, wave.Error, EOFError) as error:
print(f'FAILED {args.input}: {error}', file=sys.stderr)
return 1
seconds = combined.frame_count() / combined.frame_rate
print(f'Wrote {args.output}: {seconds:.6f} seconds, {combined.channels} channel(s)')
return 0
if __name__ == '__main__':
sys.exit(main())
Verwenden Sie Ihre eigene kompatible Datei input.wav oder erzeugen Sie einen
Ton von einer Sekunde Dauer, dessen Endpunkte bewusst nicht zusammenpassen. Die Existenzprüfungen
liefern einen Fehlerstatus, wenn die Fixture bereits vorhanden ist. Auch das FFmpeg-Flag
-n verhindert das Überschreiben:
test ! -e input.wav && test ! -L input.wav &&
ffmpeg -nostdin -hide_banner -v error -n -f lavfi \
-i 'aevalsrc=0.25*sin(2*PI*440.5*t+PI/4):s=48000:d=1' -c:a pcm_s16le input.wav
Wiederholen Sie ihn fünfmal:
.venv/bin/python loop_audio.py --repeats 5 -- input.wav repeated.wav
Zu erwarten sind Wrote repeated.wav: 5.000000 seconds, 1 channel(s) und der Status 0.
Harte Wiederholungen erhalten jeden Eingabeframe einschließlich Stille, wiederholen aber auch jeden
Sprung zwischen dem letzten und dem ersten Sample. Wenn Sie den Befehl erneut ausführen, liefert
er den Status 1 und erhält repeated.wav.
Ungültige Argumente liefern den Status 2. Ein-/Ausgabefehler, darunter
fehlende Eingabedateien, erkannte Dateikürzungen oder nicht unterstützte Sample-Formate, liefern den
Status 1. Die Prüfung der deklarierten Frames kann nicht feststellen,
ob eine Aufnahme vor dem Speichern vollständig war oder ob gültige Sample-Werte verändert wurden.
Interne Übergänge überblenden
Wählen Sie einen neuen Ausgabedateinamen und eine Überlappung von 25 ms:
.venv/bin/python loop_audio.py --repeats 5 --crossfade-ms 25 -- input.wav crossfaded.wav
Zu erwarten ist Wrote crossfaded.wav: 4.900000 seconds, 1 channel(s). Die
Operation append von Pydub überlappt das Ende
des bisher aufgebauten Audios mit dem Anfang der nächsten Kopie. Bei N
Kopien mit der Dauer D und einer Überblendungsdauer von
F beträgt die Ergebnisdauer ungefähr N × D − (N − 1) × F.
Fünf Kopien von je einer Sekunde haben vier Übergänge und verlieren damit insgesamt 100 ms.
Pydub schneidet in Millisekunden; bei Clips oder Abtastraten, die nicht zu diesem Raster passen,
kann es zu Rundungen auf Sample-Ebene kommen. Harte Wiederholungen verwenden die ursprünglichen
Frames ohne dieses Schneiden.
Gespeicherte WAV-Dateien prüfen
Untersuchen und decodieren Sie beide konkret benannten Ausgabedateien vollständig:
ffprobe -v error -select_streams a:0 \
-show_entries stream=codec_name,sample_rate,channels:format=duration -of json repeated.wav &&
ffmpeg -nostdin -v error -xerror -i repeated.wav -f null - &&
ffprobe -v error -select_streams a:0 \
-show_entries stream=codec_name,sample_rate,channels:format=duration -of json crossfaded.wav &&
ffmpeg -nostdin -v error -xerror -i crossfaded.wav -f null -
Für den erzeugten Ton sollten beide Dateien pcm_s16le,
48000 Hz und einen Kanal melden. Ihre Dauer beträgt 5 Sekunden bzw.
4,9 Sekunden. Die Decodierbefehle sollten ohne Fehler enden. Diese Prüfungen bestätigen Format,
Zeitangaben und Decodierbarkeit. Hören Sie sich die Dateien in einem Audioplayer an, um zu
beurteilen, ob die Übergänge zu Ihrer Aufnahme passen.
Eine geeignete Loop-Grenze wählen
Ein Nulldurchgang kann einen Amplitudensprung reduzieren, doch zwei Nulldurchgänge können sich in Steigung, Phase oder Kanalverhalten unterscheiden. Die Beat-Erkennung schlägt rhythmische Schnittpunkte vor; sie bestätigt nicht, dass Töne, Raumatmosphäre oder Nachhall natürlich ineinander übergehen. Stille Eingaben bleiben bei beiden Verfahren still. Eine Überblendung kann einen Transienten verwischen oder den Rhythmus verändern, indem sie jede Wiederholung verkürzt.
Das Skript überblendet nur die internen Übergänge. Es verbindet das Ende der gespeicherten Datei nicht wieder mit ihrem Anfang. Deshalb kann die endlose Wiedergabe der gesamten Ausgabe weiterhin knacken. Hören Sie sich sowohl die internen Übergänge als auch diese äußere Grenze im vorgesehenen Player an. Wählen Sie für einen Loop in einem Spiel oder für Hintergrundmusik zuerst einen musikalisch passenden Bereich und prüfen Sie beide Stereokanäle, bevor Sie die Überlappung festlegen.
Längere Dateien mit FFmpeg wiederholen
Pydub hält die Eingabe und das wachsende Ergebnis im Arbeitsspeicher. Ein vollständig geladenes Segment in Teilstücke aufzuteilen, hebt diese anfängliche Speicherbelegung nicht auf. Wenn Sie nur ganze Dateien wiederholen müssen, kann FFmpeg dies erledigen, ohne den gesamten wiederholten PCM-Puffer in Python aufzubauen:
test ! -e repeated-ffmpeg.wav && test ! -L repeated-ffmpeg.wav &&
ffmpeg -nostdin -hide_banner -v error -xerror -n -stream_loop 4 \
-i input.wav -map 0:a:0 -c:a pcm_s16le repeated-ffmpeg.wav
Die Eingabeoption -stream_loop zählt zusätzliche
Wiedergaben: 4 ergibt einschließlich der ersten fünf Kopien. Dieser
Befehl erstellt aus dem Ton eine WAV-Datei von fünf Sekunden Dauer, behält Abtastrate und Kanalzahl
bei und fügt keine Überblendung hinzu. Führen Sie diese Befehle nacheinander aus.
Die Existenzprüfungen lassen eine erneute Ausführung vor dem Aufruf von FFmpeg fehlschlagen;
-n allein kann unter FFmpeg 9.0.1 die Verweigerung des Überschreibens
mit dem Status 0 melden. -xerror sorgt dafür,
dass gemeldete Verarbeitungsfehler den Befehl fehlschlagen lassen.
Ein Fehler nach Beginn des Schreibens kann eine unvollständige neue Datei hinterlassen. Entfernen
Sie diese fehlerhafte Ausgabe vor einem erneuten Versuch. Erfolgreiches Decodieren beweist nicht,
dass eine Aufnahme vollständig war, bevor sie Ihr Skript erreichte.
Behalten Sie PCM WAV als Bearbeitungsausgabe bei und beurteilen Sie die Übergänge vor dem Encoding für die Auslieferung. Die Pydub-API dokumentiert weitere Überblendungen und Pegelanpassungen, falls Ihr gewählter Bereich diese benötigt.
