J'ai regardé le lien suivant :Couper le fichier audio en utilisant les heures de début et de fin
Mais cela ne répond pas complètement à ma question. Mon problème est :j'ai un fichier audio tel que abc.mp3
ou abc.wav
. J'ai également un fichier texte contenant les horodatages de début et de fin :
0.0 1.0 silence
1.0 5.0 music
6.0 8.0 speech
Je veux diviser l'audio en trois parties en utilisant Python et sox
/ffmpeg
, résultant ainsi en trois fichiers audio distincts.
Comment puis-je y parvenir en utilisant soit sox
ou ffmpeg
?
Plus tard, je veux calculer le MFCC correspondant à ces portions en utilisant librosa
.
J'ai Python 2.7
, ffmpeg
, et sox
sur une installation Ubuntu Linux 16.04.
Réponse acceptée :
Je viens de faire un essai rapide, très peu de tests, alors peut-être que ça va être utile. Ci-dessous repose sur ffmpeg-python, mais ce ne serait pas un défi d'écrire avec subprocess
de toute façon.
Pour le moment, le fichier d'entrée de l'heure est simplement traité comme des paires d'heures, début et fin, puis un nom de sortie. Les noms manquants sont remplacés par linecount.wav
import ffmpeg
from sys import argv
""" split_wav `audio file` `time listing`
`audio file` is any file known by local FFmpeg
`time listing` is a file containing multiple lines of format:
`start time` `end time` output name
times can be either MM:SS or S*
"""
_in_file = argv[1]
def make_time(elem):
# allow user to enter times on CLI
t = elem.split(':')
try:
# will fail if no ':' in time, otherwise add together for total seconds
return int(t[0]) * 60 + float(t[1])
except IndexError:
return float(t[0])
def collect_from_file():
"""user can save times in a file, with start and end time on a line"""
time_pairs = []
with open(argv[2]) as in_times:
for l, line in enumerate(in_times):
tp = line.split()
tp[0] = make_time(tp[0])
tp[1] = make_time(tp[1]) - tp[0]
# if no name given, append line count
if len(tp) < 3:
tp.append(str(l) + '.wav')
time_pairs.append(tp)
return time_pairs
def main():
for i, tp in enumerate(collect_from_file()):
# open a file, from `ss`, for duration `t`
stream = ffmpeg.input(_in_file, ss=tp[0], t=tp[1])
# output to named file
stream = ffmpeg.output(stream, tp[2])
# this was to make trial and error easier
stream = ffmpeg.overwrite_output(stream)
# and actually run
ffmpeg.run(stream)
if __name__ == '__main__':
main()