优化: KGM解密并行化,多线程处理block,提升服务器卡顿时转码速度
This commit is contained in:
+15
-4
@@ -9,6 +9,7 @@ from mutagen.flac import FLAC
|
|||||||
from mutagen.oggvorbis import OggVorbis
|
from mutagen.oggvorbis import OggVorbis
|
||||||
from mutagen.id3 import ID3, TIT2, TPE1, TALB, APIC
|
from mutagen.id3 import ID3, TIT2, TPE1, TALB, APIC
|
||||||
from pydub import AudioSegment
|
from pydub import AudioSegment
|
||||||
|
from concurrent.futures import ThreadPoolExecutor
|
||||||
|
|
||||||
NCM_MAGIC = b"CTENFDAM"
|
NCM_MAGIC = b"CTENFDAM"
|
||||||
CORE_KEY = b"hzHRAmso5kInbaxW"
|
CORE_KEY = b"hzHRAmso5kInbaxW"
|
||||||
@@ -262,16 +263,26 @@ class KgmDecoder:
|
|||||||
pub_len = len(self.pub_key)
|
pub_len = len(self.pub_key)
|
||||||
out = bytearray(len(audio))
|
out = bytearray(len(audio))
|
||||||
block_count = (len(audio) + BLOCK - 1) // BLOCK
|
block_count = (len(audio) + BLOCK - 1) // BLOCK
|
||||||
for block_idx in range(block_count):
|
if block_count > pub_len:
|
||||||
if block_idx >= pub_len:
|
|
||||||
raise ValueError("Key file mismatch")
|
raise ValueError("Key file mismatch")
|
||||||
|
# Pre-compute all 17 phase tables; workers only read from cache
|
||||||
|
for phase in range(17):
|
||||||
|
self._phase_tables(phase, own_key, self.pub_key)
|
||||||
|
# Parallel block decryption: each block is independent
|
||||||
|
def _decrypt_block(block_idx):
|
||||||
phase = block_idx % 17
|
phase = block_idx % 17
|
||||||
tables = self._phase_tables(phase, own_key, self.pub_key)
|
tables = self._phase_tables(phase, own_key, self.pub_key)
|
||||||
pub_value = self.pub_key[block_idx]
|
pub_value = self.pub_key[block_idx]
|
||||||
start = block_idx * BLOCK
|
start = block_idx * BLOCK
|
||||||
end = min(start + BLOCK, len(audio))
|
end = min(start + BLOCK, len(audio))
|
||||||
for col, offset in enumerate(range(start, end)):
|
blk = bytearray(end - start)
|
||||||
out[offset] = tables[col][pub_value][audio[offset]]
|
for col in range(end - start):
|
||||||
|
blk[col] = tables[col][pub_value][audio[start + col]]
|
||||||
|
return start, bytes(blk)
|
||||||
|
max_workers = min(16, max(1, block_count))
|
||||||
|
with ThreadPoolExecutor(max_workers=max_workers) as executor:
|
||||||
|
for start, blk in executor.map(_decrypt_block, range(block_count)):
|
||||||
|
out[start:start + len(blk)] = blk
|
||||||
payload = bytes(out)
|
payload = bytes(out)
|
||||||
container = _sniff_container(payload[:64])
|
container = _sniff_container(payload[:64])
|
||||||
return payload, container, {}, None
|
return payload, container, {}, None
|
||||||
|
|||||||
Reference in New Issue
Block a user