يدعم ربط برنامج الترميز الحريري python برنامج الترميز الصوتي WeChat
بيلك: بيثون + حرير
المشاريع ذات الصلة: weixin-wxpose-silk-voice
pip install pilk
SILK هو تنسيق لترميز الكلام تم تطويره بواسطة Skype وتم إصدار أحدث إصدار متاح عبر الإنترنت في عام 2012.
تم تحميل كود SILK الأصلي إلى الإصدار، بما في ذلك وثائق المواصفات
يأتي الدعم الصوتي لـ Tencent من وحدة فك ترميز Silk-v3
يحتوي الإصدار أيضًا على إصدار x64-win المُعاد ترجمته من وحدة فك ترميز Silk-v3، ويدعم كود المصدر الصيني
تشير Tencent هنا إلى الصوت، مع أخذ صوت WeChat كمثال فقط
b'#!SILK_V3'
وينتهي بـ b'xFFxFF'
، مع وجود بيانات صوتية في المنتصفb'x02'
في بداية ملف SILK القياسي، ويزيل b'xFFxFF'
في النهاية، ويترك الوسط دون تغيير.ويشار إليها مجتمعة باسم الملفات الصوتية
يتم تقسيم البيانات الصوتية إلى العديد من الإطارات المستقلة. تقوم أول بايتتين من كل إطار بتخزين حجم بيانات الإطار المتبقية، ويخزن كل إطار 20 مللي ثانية من البيانات الصوتية بشكل افتراضي.
وبناء على ذلك يمكنك كتابة دالة للحصول على مدة الملف الصوتي (هذه الوظيفة متضمنة في 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
وفقًا لمواصفات تنسيق SILK ، يمكن أن يكون إطار_ms 20, 40, 60, 80, 100
يرجى مراجعة تعليقات وثائق API في IDE للحصول على التفاصيل.
قبل استخدام pilk ، عليك أن تعرف أن التحويل بين الملفات الصوتية mp3, aac, m4a, flac, wav, ...
والملفات الصوتية يكتمل بمساعدة بيانات PCM الأولية
علاقة تحويل محددة: ملف صوتي ⇔ PCM ⇔ ملف صوتي
ملفات الصوت (الفيديو) ➜ PCM
مع ffmpeg، بالطبع تحتاج إلى ffmpeg أولاً
ffmpeg -y -i <音(视)频输入文件> -vn -ar <采样率> -ac 1 -f s16le < PCM输出文件>
-y
: يمكن إضافته أم لا، مما يشير إلى أن <ملف إخراج PCM> لا يسأل عما إذا كان موجودًا بالفعل، بل يقوم بالكتابة فوقه مباشرة-i
: لا يوجد ما يمكن قوله، تم إصلاحه، متبوعًا بـ <ملف إدخال الصوت (الفيديو)>-vn
: يشير إلى أنه لن تتم معالجة بيانات الفيديو، ويوصى بإضافتها. على الرغم من أنه لن تتم معالجة بيانات الفيديو دون إضافتها (لا يوجد شيء مثل تحويل بيانات الفيديو إلى PCM)، إلا أنه قد يتم طباعة تحذير.-ar
: ضبط معدل أخذ العينات، القيم الاختيارية هي [8000، 12000، 16000، 24000، 32000، 44100، 48000]، هنا يمكنك فهمها مباشرة كجودة الصوت-ac
: قم بتعيين عدد القنوات، والذي يجب أن يكون 1 هنا، والذي يتم تحديده بواسطة SILK-f
: يعني التحويل القسري إلى التنسيق المحدد، وبشكل عام يجب أن يكون s16le ، وهو ما يعني 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 ➜ الملفات الصوتية
ffmpeg -y -f s16le -ar <采样率> -ac <声道数> -i < PCM输入文件> <音频输出文件>
-f
: يجب أن يكون s16le
، والذي يتم تحديده أيضًا بواسطة SILK-ar
: نفس ما ورد أعلاه-ac
: المعنى هو نفسه المذكور أعلاه، والقيمة عشوائية<音频输出文件>
: يجب أن يكون الامتداد دقيقًا عندما لا يتم تحديد التنسيق، سيحدد ffmpeg التنسيق الذي يجب إخراجه بناءً على امتداد ملف الإخراج المحدد.ffmpeg -y -f s16le -ar 16000 -i test.pcm test.mp3
يمكن أيضًا استبدال ffmpeg بربط python ffmpeg، ومن المستحسن أن تدرس PyAV بنفسك، لذلك لن أخوض في التفاصيل هنا.
بعد الحديث عن الملفات الصوتية ⇔ PCM، الخطوة التالية هي استخدام pilk لتحويل 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 )
استخدم Pudub للاعتماد على 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
يوصى باستخدام 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