Как я могу программно определить частоту дискретизации файла WAV?

Есть программа написанная на python, которая распознаёт текст с использованной библиотекой vosk. Для распознавания текста нужно передать частоту дискретизации и модель языка этой строкой : KaldiRecognizer(model, 96000), где 96000 - это сама частота. чтобы определить частоту дискретизации файла я использую следующий код:

with wave.open(r'a.wav', "rb") as wave_file:
    frame_rate = wave_file.getframerate()
    print(frame_rate)

НО! Практически во всех файлах он определяет частоту: 48000, для некоторых аудио файлов она почему-то не подходит и выводится какой-то бред а не текст (просто набор слов), тобиш vosk не правильно определяет текст в аудио, решается эта проблема ручной заменой частоты на нужную, постоянно необходимо подбирать её. в чём может быть проблема? до этого, преобразовывал аудио файл в онлайн конвертации. Хотелось бы автоматизировать процесс.


Ответы (2 шт):

Автор решения: wazzapKawaii

Полагаю, проблема в теории

Может быть несколько причин, по которым ваш код неправильно определяет частоту дискретизации некоторых аудиофайлов:

1. Неподдерживаемый аудиоформат: Модуль wave, используемый в вашем коде, поддерживает только ограниченный набор аудиоформатов. Если аудиофайл, который вы пытаетесь открыть, находится в формате, который модуль не поддерживает, он может возвращать неправильную частоту. Возможно, вам потребуется использовать другой модуль, поддерживающий более широкий спектр аудиоформатов, например модуль pydub.

2. Неправильная информация о заголовке: Некоторые аудиофайлы могут содержать неправильную информацию о заголовке, которая не соответствует фактической частоте дискретизации. Это может произойти, когда файл создан неправильно или когда он конвертируется из одного формата в другой. В этом случае вам, возможно, потребуется вручную установить частоту дискретизации при передаче файла в библиотеку Vosk.

3. Кодирование с переменной скоростью передачи данных (VBR): Некоторые аудиофайлы могут иметь кодировку с переменной скоростью передачи данных, что означает, что скорость передачи данных изменяется по всему файлу. В этом случае частота, сообщаемая модулем wave, может быть неточной, и вам может потребоваться использовать другой метод для определения частоты дискретизации.

Чтобы автоматизировать процесс, вы можете попробовать использовать вышеупомянутый модуль pydub для преобразования аудиофайлов в поддерживаемый формат с фиксированной частотой дискретизации перед передачей их в библиотеку Vosk. Вы также можете попробовать использовать модуль mediainfo для извлечения частоты дискретизации непосредственно из метаданных файла вместо того, чтобы полагаться на модуль wave.

→ Ссылка
Автор решения: InterceptorTSK

WAV file header

This is an example of a WAV file header (44 bytes). Data is stored in little-endian byte order.

[Master RIFF chunk]
FileTypeBlocID  (4 bytes) : Identifier « RIFF »  (0x52, 0x49, 0x46, 0x46)
FileSize        (4 bytes) : Overall file size minus 8 bytes
FileFormatID    (4 bytes) : Format = « WAVE »  (0x57, 0x41, 0x56, 0x45)

[Chunk describing the data format]
FormatBlocID    (4 bytes) : Identifier « fmt␣ »  (0x66, 0x6D, 0x74, 0x20)
BlocSize        (4 bytes) : Chunk size minus 8 bytes, which is 16 bytes here  (0x10)
AudioFormat**   (2 bytes) : Audio format** (1: PCM integer, 3: IEEE 754 float)
NbrChannels     (2 bytes) : Number of channels
>>Frequency<<   (4 bytes) : Sample rate (in hertz)
BytePerSec      (4 bytes) : Number of bytes to read per second (Frequency * BytePerBloc).
BytePerBloc     (2 bytes) : Number of bytes per block (NbrChannels * BitsPerSample / 8).
BitsPerSample   (2 bytes) : Number of bits per sample

[Chunk containing the sampled data]
DataBlocID      (4 bytes) : Identifier « data »  (0x64, 0x61, 0x74, 0x61)
DataSize        (4 bytes) : SampledData size
SampledData

Сами расколупайте header, проверьте header (заголовок) ваших wav-файлов на соответствие формата заголовка. Если не ваши wav-файлы как то изменены в заголовке, ну значит кто то использует нестандартный заголовок.

Frequency по стандарту - это 24,25,26,27-ой байты, от начала файла. Прочтите эти четыре байта, превратите в int (беззнаковый int), получите частоту.

Не забываем про little-endian byte order. Пример

file_byte[24] = 0x44
file_byte[25] = 0xAC
file_byte[26] = 0x00
file_byte[27] = 0x00

Что бы собрать частоту, собираем байты в обратном порядке (зависит от проца, ОС, рантайма итд)

44 AC 00 00 -> 00 00 AC 44 -> 44100 Hz (бинго!)

Но это не решение, нужно весь заголовок чекнуть на соответствие стандарту. Если заголовок не проходит по стандарту - значит его нужно раскапывать отдельно, ручками. Смотреть что там в этом нестандартном заголовке вкарячено.

P.s: Какой то wav-файл, открытый в Visual Studio Binary Editor

File -> Open -> Open With -> Binary Editor

Выделены 24,25,26,27-ые байты, они и есть 44100 Hz

WAV Header, 24,25,26,27 bytes

**Упд: Если вы проверяете [валидируете] заголовок [44 байта] на полное соответствие, то поле AudioFormat (со значениями 1,3) расширено IANA до более широкого стандарта. Допустимые значения этого поля, как справедливо указал @eri - описано в расширенном стандарте от IANA. См. комментарии от @eri.

→ Ссылка