Die Python-Seide-Codec-Bindung unterstützt den WeChat-Sprachcodec
Pilk: Python + Seide
Verwandte Projekte: weixin-wxposed-silk-voice
pip install pilk
SILK ist ein von Skype entwickeltes Sprachcodierungsformat. Die neueste online verfügbare Version wurde 2012 veröffentlicht.
Der Originalcode von SILK wurde zum Release hochgeladen, einschließlich der Spezifikationsdokumente
Die Tencent- Sprachunterstützung erfolgt über den Silk-v3-Decoder
Die Veröffentlichung enthält auch die neu kompilierte x64-Win- Version von Silk-v3-Decoder, unterstützt chinesischen Quellcode
Tencent bezieht sich hier auf Sprache und nimmt nur die WeChat-Sprache als Beispiel
b'#!SILK_V3'
und endet mit b'xFFxFF'
, mit Sprachdaten in der Mitteb'x02'
am Anfang der Standard -SILK -Datei ein, entfernt b'xFFxFF'
am Ende und lässt die Mitte unverändert.werden zusammenfassend als Sprachdateien bezeichnet
Die Sprachdaten sind in viele unabhängige Frames unterteilt. Die ersten beiden Bytes jedes Frames speichern standardmäßig die Größe der verbleibenden Frame- Daten .
Auf dieser Grundlage können Sie eine Funktion schreiben, um die Dauer der Sprachdatei zu ermitteln (diese Funktion ist in pilk enthalten).
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
Gemäß der SILK- Formatspezifikation kann „frame_ms“ 20, 40, 60, 80, 100
sein
Weitere Informationen finden Sie in den Kommentaren zur API-Dokumentation in der IDE.
Bevor Sie Pilk verwenden, müssen Sie wissen, dass die Konvertierung zwischen Audiodateien mp3, aac, m4a, flac, wav, ...
und Sprachdateien mithilfe von PCM-Rohdaten erfolgt
Spezifische Konvertierungsbeziehung: Audiodatei ⇔ PCM ⇔ Sprachdatei
Audio-(Video-)Dateien ➜ PCM
Bei ffmpeg müssen Sie natürlich zuerst ffmpeg haben
ffmpeg -y -i <音(视)频输入文件> -vn -ar <采样率> -ac 1 -f s16le < PCM输出文件>
-y
: Kann hinzugefügt werden oder nicht, was darauf hinweist, dass <PCM-Ausgabedatei> nicht fragt, ob sie bereits vorhanden ist, sondern sie direkt überschreibt-i
: Nichts zu sagen, behoben, gefolgt von <Audio-(Video-)Eingabedatei>-vn
: Zeigt an, dass Videodaten nicht verarbeitet werden. Es wird empfohlen, sie hinzuzufügen. Obwohl die Videodaten nicht verarbeitet werden, ohne sie hinzuzufügen (es gibt keine Möglichkeit, Videodaten in PCM zu konvertieren), wird möglicherweise eine Warnung ausgegeben.-ar
: Stellen Sie die Abtastrate ein. Die optionalen Werte sind [8000, 12000, 16000, 24000, 32000, 44100, 48000]. Hier können Sie dies direkt als Klangqualität verstehen-ac
: Legen Sie die Anzahl der Kanäle fest, die hier 1 sein muss, was von SILK bestimmt wird-f
: bedeutet erzwungene Konvertierung in das angegebene Format. Im Allgemeinen muss es sich um s16le handeln, was 16-bit short integer Little-Endian data
bedeutetffmpeg -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 ➜ Audiodateien
ffmpeg -y -f s16le -ar <采样率> -ac <声道数> -i < PCM输入文件> <音频输出文件>
-f
: Dies muss s16le
sein, was auch von SILK bestimmt wird-ar
: Das Gleiche wie oben-ac
: Die Bedeutung ist die gleiche wie oben, der Wert ist willkürlich<音频输出文件>
: Die Erweiterung muss korrekt sein. Wenn das Format nicht angegeben ist, bestimmt ffmpeg das Format, das ausgegeben werden muss, basierend auf der angegebenen Ausgabedateierweiterung.ffmpeg -y -f s16le -ar 16000 -i test.pcm test.mp3
ffmpeg kann auch durch die Python-ffmpeg-Bindung ersetzt werden. Es wird empfohlen, dass Sie PyAV selbst studieren, daher werde ich hier nicht auf Details eingehen.
Nachdem wir über Audiodateien ⇔ PCM gesprochen haben, besteht der nächste Schritt darin, Pilk zum Konvertieren von PCM ⇔ Sprachdateien zu verwenden.
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 )
Verwenden Sie Pudub, um von ffmpeg abhängig zu sein
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
Empfohlene Verwendung von 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