การรวมตัวแปลงสัญญาณไหมหลามรองรับตัวแปลงสัญญาณเสียง WeChat
พิลค์: หลาม + ไหม
โครงการที่เกี่ยวข้อง: weixin-wxposed-silk-voice
pip install pilk
SILK เป็นรูปแบบการเข้ารหัสเสียงพูดที่พัฒนาโดย Skype เวอร์ชันล่าสุดที่เผยแพร่ทางออนไลน์ในปี 2012
รหัสต้นฉบับ ของ SILK ได้รับการอัปโหลดไปยัง Release แล้ว รวมถึงเอกสารข้อกำหนดด้วย
การสนับสนุนด้วยเสียง ของ Tencent มาจาก silk-v3-decoder
การเปิดตัวยังประกอบด้วย silk-v3-decoder เวอร์ชัน x64-win ที่คอมไพล์ใหม่ รองรับซอร์สโค้ดภาษาจีน
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 frame_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 output file> ไม่ได้ถามว่ามีอยู่แล้วหรือไม่ แต่จะเขียนทับโดยตรง-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