优化: KGM解密并行化,多线程处理block,提升服务器卡顿时转码速度

This commit is contained in:
ypshidifu
2026-09-17 21:32:45 +08:00
parent c6a0125ec2
commit ca8c8aa490
+15 -4
View File
@@ -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