La liaison du codec en soie python prend en charge le codec vocal WeChat
pilk: python + soie
Projets connexes : weixin-wxposed-silk-voice
pip install pilk
SILK est un format de codage vocal développé par Skype . La dernière version disponible en ligne a été publiée en 2012.
Le code original de SILK a été téléchargé dans Release, y compris les documents de spécifications
La prise en charge vocale de Tencent provient de Silk-v3-decoder
La version contient également la version x64-win recompilée de Silk-v3-decoder, prend en charge le chinois, le code source
Tencent fait ici référence à la voix, en prenant uniquement la voix de WeChat comme exemple
b'#!SILK_V3'
et se termine par b'xFFxFF'
, avec les données vocales au milieub'x02'
au début du fichier SILK standard, supprime b'xFFxFF'
à la fin et laisse le milieu inchangésont collectivement appelés fichiers vocaux
Les données vocales sont divisées en plusieurs trames indépendantes. Les deux premiers octets de chaque trame stockent la taille des données de trame restantes. Chaque trame stocke 20 ms de données audio par défaut.
Sur cette base, vous pouvez écrire une fonction pour obtenir la durée du fichier vocal (cette fonction est incluse dans 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
Selon la spécification du format SILK , frame_ms peut être 20, 40, 60, 80, 100
Veuillez consulter les commentaires de la documentation de l'API dans l'EDI pour plus de détails.
Avant d'utiliser Pilk , vous devez savoir que la conversion entre les fichiers audio mp3, aac, m4a, flac, wav, ...
et les fichiers vocaux se fait à l'aide de données brutes PCM.
Relation de conversion spécifique : fichier audio ⇔ PCM ⇔ fichier vocal
Fichiers audio (vidéo) ➜ PCM
Avec ffmpeg, bien sûr, vous devez d'abord avoir ffmpeg
ffmpeg -y -i <音(视)频输入文件> -vn -ar <采样率> -ac 1 -f s16le < PCM输出文件>
-y
: Peut être ajouté ou non, indiquant que le <fichier de sortie PCM> ne demande pas s'il existe déjà, mais l'écrase directement.-i
: Rien à dire, corrigé, suivi de <fichier d'entrée audio (vidéo)>-vn
: Indique que les données vidéo ne seront pas traitées. Il est recommandé de les ajouter. Bien que les données vidéo ne soient pas traitées sans les ajouter (la conversion des données vidéo en PCM n'existe pas), un avertissement peut être imprimé.-ar
: Définissez le taux d'échantillonnage, les valeurs facultatives sont [8000, 12000, 16000, 24000, 32000, 44100, 48000], ici vous pouvez directement le comprendre comme la qualité sonore-ac
: Définit le nombre de canaux, qui doit être 1 ici, qui est déterminé par SILK-f
: signifie une conversion forcée au format spécifié, généralement il doit s'agir de s16le , ce qui signifie 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 ➜ Fichiers audio
ffmpeg -y -f s16le -ar <采样率> -ac <声道数> -i < PCM输入文件> <音频输出文件>
-f
: Cela doit être s16le
, qui est également déterminé par SILK-ar
: Idem que ci-dessus-ac
: La signification est la même que ci-dessus, la valeur est arbitraire<音频输出文件>
: L'extension doit être précise. Lorsque le format n'est pas spécifié, ffmpeg déterminera le format qui doit être sorti en fonction de l'extension du fichier de sortie donnée.ffmpeg -y -f s16le -ar 16000 -i test.pcm test.mp3
ffmpeg peut également être remplacé par la liaison python ffmpeg. Il est recommandé d'étudier PyAV par vous-même, je n'entrerai donc pas dans les détails ici.
Après avoir parlé des fichiers audio ⇔ PCM, l'étape suivante consiste à utiliser pilk pour convertir les fichiers vocaux 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 )
Utilisez Pudub pour dépendre 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
Utilisation recommandée de 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