pengikatan codec sutra python mendukung codec suara WeChat
pilk: python + sutra
Proyek terkait: weixin-wxpose-silk-voice
pip install pilk
SILK adalah format pengkodean ucapan yang dikembangkan oleh Skype . Versi terbaru yang tersedia online dirilis pada tahun 2012.
Kode asli SILK telah diunggah ke Rilis, termasuk dokumen spesifikasi
Dukungan suara Tencent berasal dari silk-v3-decoder
Rilis juga berisi decoder silk-v3 versi x64-win yang telah dikompilasi ulang, mendukung kode sumber berbahasa Mandarin
Tencent di sini mengacu pada suara, hanya mengambil suara WeChat sebagai contoh
b'#!SILK_V3'
dan diakhiri dengan b'xFFxFF'
, dengan data suara di tengahnyab'x02'
di awal file SILK standar, menghapus b'xFFxFF'
di akhir, dan membiarkan bagian tengahnya tidak berubah.secara kolektif disebut sebagai file suara
Data suara dibagi menjadi banyak frame independen. Dua byte pertama dari setiap frame menyimpan ukuran data frame yang tersisa. Setiap frame menyimpan 20 ms data audio secara default.
Berdasarkan hal ini, Anda dapat menulis fungsi untuk mendapatkan durasi file suara (fungsi ini termasuk dalam 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
Menurut spesifikasi format SILK , frame_ms bisa berupa 20, 40, 60, 80, 100
Silakan periksa komentar dokumentasi API di IDE untuk detailnya.
Sebelum menggunakan pilk , perlu Anda ketahui bahwa konversi antara file audio mp3, aac, m4a, flac, wav, ...
dan file suara diselesaikan dengan bantuan data mentah PCM
Hubungan konversi spesifik: file audio ⇔ PCM ⇔ file suara
File audio (video) ➜ PCM
Dengan ffmpeg tentunya Anda harus memiliki ffmpeg terlebih dahulu
ffmpeg -y -i <音(视)频输入文件> -vn -ar <采样率> -ac 1 -f s16le < PCM输出文件>
-y
: Dapat ditambahkan atau tidak, menandakan bahwa <PCM output file> tidak menanyakan apakah sudah ada, tetapi langsung menimpanya-i
: Tidak ada yang perlu dikatakan, sudah diperbaiki, diikuti dengan <file input audio (video)>-vn
: Menandakan bahwa data video tidak akan diproses. Disarankan untuk menambahkannya. Meskipun data video tidak akan diproses tanpa menambahkannya (tidak ada yang namanya konversi data video ke PCM), peringatan mungkin akan dicetak.-ar
: Atur sampling rate, nilai opsionalnya adalah [8000, 12000, 16000, 24000, 32000, 44100, 48000], di sini Anda dapat langsung memahaminya sebagai kualitas suara-ac
: Mengatur jumlah channel yang disini harus 1 yang ditentukan oleh SILK-f
: berarti konversi paksa ke format yang ditentukan, umumnya harus s16le , yang berarti 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 ➜ File audio
ffmpeg -y -f s16le -ar <采样率> -ac <声道数> -i < PCM输入文件> <音频输出文件>
-f
: Ini harus s16le
, yang juga ditentukan oleh SILK-ar
: Sama seperti di atas-ac
: Artinya sama seperti di atas, nilainya sewenang-wenang<音频输出文件>
: Ekstensi harus akurat. Jika format tidak ditentukan, ffmpeg akan menentukan format keluaran berdasarkan ekstensi file keluaran yang diberikan.ffmpeg -y -f s16le -ar 16000 -i test.pcm test.mp3
ffmpeg juga bisa diganti dengan pengikatan python ffmpeg. Disarankan agar Anda mempelajari PyAV sendiri, jadi saya tidak akan membahas detailnya di sini.
Setelah berbicara tentang file audio ⇔ PCM, langkah selanjutnya adalah menggunakan pilk untuk mengkonversi file suara 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 )
Gunakan pudub untuk bergantung pada 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
Direkomendasikan menggunakan 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