Извлечение характеристик из блоба с помощью Librosa

Я пытаюсь записать голосовое сообщение во фронтенде и отправить его в бэкенд Django, чтобы проверить его на соответствие ML-алгоритму распознавания пола по голосу. Во фронтенде я записываю голос с помощью videojs-record и использую AJAX для отправки блоба в бэкенд следующим образом:

На бэкенде я пытаюсь использовать wave, чтобы сохранить файл как правильный .wav, например так:

def post(self, request):
        f = request.FILES['file']

        with open('file.wav', 'wb+') as destination:
            for chunk in f.chunks():
                destination.write(chunk)

        with open('file.wav', 'rb') as file:
            file_content = file.read()
            audio = wave.open('test.wav', 'wb')
            audio.setnchannels(1)
            audio.setnframes(1)
            audio.setsampwidth(1)
            audio.setframerate(8000)
            audio.writeframes(file_content)
            audio.close()

        (prediction, probability) = predict('test.wav')

        context["prediction"] = prediction
        context["probability"] = probability*100

        os.remove(file_name)

        return render(request, self.template_name, context=context)

Здесь я попробовал две вещи. Первая попытка заключалась в том, чтобы сохранить блоб непосредственно в файл, используя open with 'wb'. Проблема с этим подходом в том, что librosa жалуется, что тип файла не распознан. Другая попытка была с помощью wave, но что бы я ни пробовал, файл, сохраненный с помощью wave, дает шум, и алгоритм предсказания не работает. Вот как я хотел бы использовать файл с записанным голосом для предсказания:

def predict(file_name):
    # construct the model
    model = create_model()

    # load the saved/trained weights
    model.load_weights('model.h5')

    # extract features and reshape it
    features = extract_feature(file_name, mel=True).reshape(1, -1)

    # predict the gender!
    male_prob = model.predict(features)[0][0]
    female_prob = 1 - male_prob

    gender = "male" if male_prob > female_prob else "female"

    if gender == "male":
        return (gender, male_prob)

    return (gender, female_prob)

А вот функция extract_feature, в которой я загружаю файл и обрабатываю его:

def extract_feature(file_name, **kwargs):
    mfcc = kwargs.get("mfcc")
    chroma = kwargs.get("chroma")
    mel = kwargs.get("mel")
    contrast = kwargs.get("contrast")
    tonnetz = kwargs.get("tonnetz")
    X, sample_rate = librosa.core.load(file_name)

    if chroma or contrast:
        stft = np.abs(librosa.stft(X))

    result = np.array([])

    if mfcc:
        mfccs = np.mean(librosa.feature.mfcc(y=X, sr=sample_rate, n_mfcc=40).T, axis=0)
        result = np.hstack((result, mfccs))

    if chroma:
        chroma = np.mean(librosa.feature.chroma_stft(S=stft, sr=sample_rate).T,axis=0)
        result = np.hstack((result, chroma))

    if mel:
        mel = np.mean(librosa.feature.melspectrogram(X, sr=sample_rate).T,axis=0)
        result = np.hstack((result, mel))

    if contrast:
        contrast = np.mean(librosa.feature.spectral_contrast(S=stft, sr=sample_rate).T,axis=0)
        result = np.hstack((result, contrast))

    if tonnetz:
        tonnetz = np.mean(librosa.feature.tonnetz(y=librosa.effects.harmonic(X), sr=sample_rate).T,axis=0)
        result = np.hstack((result, tonnetz))

    return result

Что я делаю неправильно? Есть ли способ создать правильный WAV-файл с тем же содержимым, что и блоб, который я записываю на фронтенде? Или есть способ напрямую использовать блоб, который я получаю с фронтенда?

После некоторого копания я обнаружил инструмент ffmpeg в Linux и использовал его в python для преобразования файла из формата WebM в WAV. Вот решение:

def post(self, request):
        webm_file = str(datetime.datetime.now()) + ".webm"
        wav_file = str(datetime.datetime.now()) + ".wav"

        f = request.FILES['file']

        with open(webm_file, 'wb+') as destination:
            for chunk in f.chunks():
                destination.write(chunk)
            destination.close()

        # convert file from WebM to WAV format
        subprocess.run(["ffmpeg", "-i", webm_file, "-vn", wav_file])

        (prediction, probability) = predict(wav_file)

        context["prediction"] = prediction
        context["probability"] = probability*100

        os.remove(webm_file)
        os.remove(wav_file)

        return render(request, self.template_name, context=context)
Вернуться на верх