El enlace del códec Python Silk admite el códec de voz WeChat
pilk: pitón + seda
Proyectos relacionados: weixin-wxposed-silk-voice
pip install pilk
SILK es un formato de codificación de voz desarrollado por Skype . La última versión disponible en línea se lanzó en 2012.
El código original de SILK se ha subido a la versión, incluidos los documentos de especificaciones
El soporte de voz de Tencent proviene del decodificador Silk-v3
La versión también contiene la versión x64-win recompilada del decodificador Silk-v3, admite código fuente en chino.
Tencent aquí se refiere a la voz y solo toma la voz de WeChat como ejemplo.
b'#!SILK_V3'
y termina con b'xFFxFF'
, con datos de voz en el medio.b'x02'
al principio del archivo SILK estándar, elimina b'xFFxFF'
al final y deja el medio sin cambios.se denominan colectivamente archivos de voz
Los datos de voz se dividen en muchos cuadros independientes. Los primeros dos bytes de cada cuadro almacenan el tamaño de los datos del cuadro restante. Cada cuadro almacena 20 ms de datos de audio de forma predeterminada.
En base a esto, puede escribir una función para obtener la duración del archivo de voz (esta función está incluida en pilk )
def get_duration ( silk_path : str , frame_ms : int = 20 ) -> int :
"""获取 silk 文件持续时间,单位:ms"""
with open ( silk_path , 'rb' ) as silk :
tencent = False
if silk . read ( 1 ) == b' x02 ' :
tencent = True
silk . seek ( 0 )
if tencent :
silk . seek ( 10 )
else :
silk . seek ( 9 )
i = 0
while True :
size = silk . read ( 2 )
if len ( size ) != 2 :
break
i += 1
size = size [ 0 ] + size [ 1 ] * 16
silk . seek ( silk . tell () + size )
return i * frame_ms
Según la especificación del formato SILK , frame_ms puede ser 20, 40, 60, 80, 100
Consulte los comentarios de la documentación de la API en el IDE para obtener más detalles.
Antes de usar pilk , debe saber que la conversión entre archivos de audio mp3, aac, m4a, flac, wav, ...
y archivos de voz se completa con la ayuda de datos sin procesar PCM.
Relación de conversión específica: archivo de audio ⇔ PCM ⇔ archivo de voz
Archivos de audio (vídeo) ➜ PCM
Con ffmpeg, por supuesto, primero debes tener ffmpeg
ffmpeg -y -i <音(视)频输入文件> -vn -ar <采样率> -ac 1 -f s16le < PCM输出文件>
-y
: se puede agregar o no, lo que indica que <archivo de salida PCM> no pregunta si ya existe, sino que lo sobrescribe directamente.-i
: Nada que decir, arreglado, seguido de <archivo de entrada de audio (video)>-vn
: Indica que los datos de video no se procesarán. Se recomienda agregarlos. Aunque los datos de video no se procesarán sin agregarlos (no existe la conversión de datos de video a PCM), es posible que se imprima una advertencia.-ar
: establece la frecuencia de muestreo, los valores opcionales son [8000, 12000, 16000, 24000, 32000, 44100, 48000], aquí puedes entenderlo directamente como la calidad del sonido.-ac
: establece el número de canales, que aquí debe ser 1 , que está determinado por SILK-f
: significa conversión forzada al formato especificado, generalmente debe ser s16le , que significa 16-bit short integer Little-Endian data
ffmpeg -y -i mv.mp4 -vn -ar 44100 -ac 1 -f s16le mv.pcm
ffmpeg -y -i music.mp3 -ar 44100 -ac 1 -f s16le music.pcm
PCM ➜ Archivos de audio
ffmpeg -y -f s16le -ar <采样率> -ac <声道数> -i < PCM输入文件> <音频输出文件>
-f
: debe ser s16le
, que también está determinado por SILK-ar
: Igual que arriba-ac
: El significado es el mismo que el anterior, el valor es arbitrario.<音频输出文件>
: La extensión debe ser precisa. Cuando no se especifica el formato, ffmpeg determinará el formato que se debe generar en función de la extensión del archivo de salida dada.ffmpeg -y -f s16le -ar 16000 -i test.pcm test.mp3
ffmpeg también se puede reemplazar con el enlace ffmpeg de Python. Se recomienda que estudie PyAV usted mismo, por lo que no entraré en detalles aquí.
Después de hablar de archivos de audio ⇔ PCM, el siguiente paso es usar pilk para convertir archivos de voz PCM ⇔.
import pilk
# pcm_rate 参数必须和 使用 ffmpeg 转 音频 到 PCM 文件时,使用的 `-ar` 参数一致
# pcm_rate 参数必须和 使用 ffmpeg 转 音频 到 PCM 文件时,使用的 `-ar` 参数一致
# pcm_rate 参数必须和 使用 ffmpeg 转 音频 到 PCM 文件时,使用的 `-ar` 参数一致
duration = pilk . encode ( "test.pcm" , "test.silk" , pcm_rate = 44100 , tencent = True )
print ( "语音时间为:" , duration )
import pilk
# pcm_rate 参数必须和 使用 ffmpeg 转 音频 到 PCM 文件时,使用的 `-ar` 参数一致
duration = pilk . decode ( "test.silk" , "test.pcm" )
print ( "语音时间为:" , duration )
Utilice pudub para depender de ffmpeg
import os , pilk
from pydub import AudioSegment
def convert_to_silk ( media_path : str ) -> str :
"""将输入的媒体文件转出为 silk, 并返回silk路径"""
media = AudioSegment . from_file ( media_path )
pcm_path = os . path . basename ( media_path )
pcm_path = os . path . splitext ( pcm_path )[ 0 ]
silk_path = pcm_path + '.silk'
pcm_path += '.pcm'
media . export ( pcm_path , 's16le' , parameters = [ '-ar' , str ( media . frame_rate ), '-ac' , '1' ]). close ()
pilk . encode ( pcm_path , silk_path , pcm_rate = media . frame_rate , tencent = True )
return silk_path
Recomendado usando pyav
import os
import av
import pilk
def to_pcm ( in_path : str ) -> tuple [ str , int ]:
"""任意媒体文件转 pcm"""
out_path = os . path . splitext ( in_path )[ 0 ] + '.pcm'
with av . open ( in_path ) as in_container :
in_stream = in_container . streams . audio [ 0 ]
sample_rate = in_stream . codec_context . sample_rate
with av . open ( out_path , 'w' , 's16le' ) as out_container :
out_stream = out_container . add_stream (
'pcm_s16le' ,
rate = sample_rate ,
layout = 'mono'
)
try :
for frame in in_container . decode ( in_stream ):
frame . pts = None
for packet in out_stream . encode ( frame ):
out_container . mux ( packet )
except :
pass
return out_path , sample_rate
def convert_to_silk ( media_path : str ) -> str :
"""任意媒体文件转 silk, 返回silk路径"""
pcm_path , sample_rate = to_pcm ( media_path )
silk_path = os . path . splitext ( pcm_path )[ 0 ] + '.silk'
pilk . encode ( pcm_path , silk_path , pcm_rate = sample_rate , tencent = True )
os . remove ( pcm_path )
return silk_path