Tengo este problema 

Asi se escriptan los datos 
function encryptChunk($chunk, $iv, $key)
{
    try {
        // Convertir clave hex a binario
        $binary_key = hex2bin($key);
        streamLog("Longitud de la clave binaria: " . strlen($binary_key));

        if ($binary_key === false) {
            throw new Exception('Error al convertir la clave hexadecimal a binario');
        }

        // Encriptar sin padding manual (usar el padding automático de OpenSSL)
        $encrypted = openssl_encrypt(
            $chunk,
            'AES-256-CBC',
            $binary_key,
            OPENSSL_RAW_DATA,  // Solo usar OPENSSL_RAW_DATA
            $iv
        );

        if ($encrypted === false) {
            throw new Exception("Error en la encriptación: " . openssl_error_string());
        }

        // Agregar información de longitud al inicio del chunk encriptado
        $length_prefix = pack('N', strlen($encrypted));  // 4 bytes para la longitud
        $final_data = $length_prefix . $encrypted;

        $encrypted_length = strlen($final_data);
        header('Content-Length: ' . $encrypted_length);
        header('X-Encrypted-Length: ' . $encrypted_length);
        header('X-Original-Length: ' . strlen($chunk));

        streamLog("Encriptación exitosa - Longitud datos encriptados: " . strlen($final_data));
        streamLog("Primeros bytes encriptados (hex): " . bin2hex(substr($encrypted, 0, 16)));

        return $final_data;
    } catch (Exception $e) {
        streamLog("Error en encryptChunk: " . $e->getMessage());
        throw $e;
    }
}

(RESUMEN DE ESTA FUNCION )
function audioStreamEnd($data) {
    // Configuración de streaming
        $size = filesize($file);
        $length = $size;
        $start = 0;
        $end = $size - 1;
        $etag = '"' . md5($file . filemtime($file)) . '"';

        streamLog("Tamaño del archivo: $size bytes");
        header('Content-Type: audio/mpeg');
        header('Accept-Ranges: bytes');
        header('X-Content-Type-Options: nosniff');
        header("Content-Length: " . $length);
        header("Content-Range: bytes $start-$end/$size");
        streamLog("Encabezados establecidos: Content-Length = " . $length . ", Content-Range = bytes $start-$end/$size");

        // Gestión de caché del navegador
        if (defined('ENABLE_BROWSER_AUDIO_CACHE') && ENABLE_BROWSER_AUDIO_CACHE) {
            $cache_time = 60 * 60 * 24; // 24 horas
            header('Cache-Control: private, must-revalidate, max-age=' . $cache_time);
            header('ETag: ' . $etag);

            if (isset($_SERVER['HTTP_IF_NONE_MATCH']) && $_SERVER['HTTP_IF_NONE_MATCH'] == $etag) {
                header('HTTP/1.1 304 Not Modified');
                exit;
            }
        } else {
            header('Cache-Control: no-store, no-cache, must-revalidate, max-age=0');
            header('Pragma: no-cache');
        }

        // Manejo de ranges para streaming
        if (isset($_SERVER['HTTP_RANGE'])) {
            list(, $range) = explode('=', $_SERVER['HTTP_RANGE'], 2);
            streamLog("Solicitando rango: $range");

            if (strpos($range, ',') !== false) {
                header('HTTP/1.1 416 Requested Range Not Satisfiable');
                header("Content-Range: bytes $start-$end/$size");
                exit;
            }

            if ($range == '-') {
                $c_start = $size - substr($range, 1);
                $c_end = $end;
            } else {
                $range = explode('-', $range);
                $c_start = $range[0];
                $c_end = (isset($range[1]) && is_numeric($range[1])) ? $range[1] : $size;
            }

            $c_end = ($c_end > $end) ? $end : $c_end;

            if ($c_start > $c_end || $c_start > $size - 1 || $c_end >= $size) {
                header('HTTP/1.1 416 Requested Range Not Satisfiable');
                header("Content-Range: bytes $start-$end/$size");
                exit;
            }

            $start = $c_start;
            $end = $c_end;
            $length = $end - $start + 1;
            fseek($fp, $start);
            streamLog("Rango ajustado: $start - $end");
            header('HTTP/1.1 206 Partial Content');
        }

        // Configuración de encriptación
        $buffer_size = 8192; // 8KB
        $sent = 0;
        $rate_limit = 512 * 1024; // 512KB por segundo
        $sleep_time = ($buffer_size / $rate_limit) * 1000000; // Convertir a microsegundos


        if (defined('ENABLE_AUDIO_ENCRYPTION') && ENABLE_AUDIO_ENCRYPTION) {
            $iv = openssl_random_pseudo_bytes(16);
            if ($iv === false) {
                throw new Exception('No se pudo generar el IV');
            }
            header('X-Encryption-IV: ' . base64_encode($iv));

            if (!isset($_ENV['AUDIOCLAVE'])) {
                throw new Exception('Clave de encriptación no configurada');
            }
            $key = $_ENV['AUDIOCLAVE'];


            if ($length <= $buffer_size) {
                $chunk = fread($fp, $length);
                $encrypted_chunk = encryptChunk($chunk, $iv, $key);
                echo $encrypted_chunk;
            } else {
                // Para archivos grandes, procesar en chunks
                while (!feof($fp) && $sent < $length) {
                    $remaining = $length - $sent;
                    $chunk_size = min($buffer_size, $remaining);
                    $chunk = fread($fp, $chunk_size);

                    if ($chunk === false) {
                        break;
                    }

                    $encrypted_chunk = encryptChunk($chunk, $iv, $key);
                    echo $encrypted_chunk;
                    $sent += strlen($chunk);  // Usar la longitud del chunk original

                    flush();
                    if ($sleep_time > 0) {
                        usleep($sleep_time);
                    }
                }
            }
        }

}

y luego en el cliente dice esto

Iniciando carga de audio - PostID: 266762 wavejs.js:242:13
Content-Length obtenido: -1 wavejs.js:272:21
Procesando chunk: 
Object { totalLength: 8212, chunkLength: 8208, dataLength: 8208 }
wavejs.js:349:21
Procesado 8212 de -1 bytes wavejs.js:300:29
Transmisión completa wavejs.js:283:29
Audio final combinado: 
Object { totalLength: 8192, chunks: 1 } 

en el servidor dice
2024-11-08 09:01:53 - Procesando transmisión para audio_id: 272499
2024-11-08 09:01:53 - Usando archivo cacheado: /var/www/wordpress/wp-content/uploads/audio_cache/audio_272499.cache
2024-11-08 09:01:53 - Tamaño del archivo: 160540 bytes
2024-11-08 09:01:53 - Encabezados establecidos: Content-Length = 160540, Content-Range = bytes 0-160539/160540
2024-11-08 09:01:53 - Iniciando encriptación de chunk con parámetros:
2024-11-08 09:01:53 - Longitud del chunk: 8192
2024-11-08 09:01:53 - Longitud del IV: 16
2024-11-08 09:01:53 - Longitud de la clave hex: 64
2024-11-08 09:01:53 - Longitud de la clave binaria: 32
2024-11-08 09:01:53 - Encriptación exitosa - Longitud datos encriptados: 8212
2024-11-08 09:01:53 - Primeros bytes encriptados (hex): ea6f995358862d45cd5f49f37789ee8b
2024-11-08 09:01:53 - Iniciando encriptación de chunk con parámetros:
2024-11-08 09:01:53 - Longitud del chunk: 8192
2024-11-08 09:01:53 - Longitud del IV: 16
2024-11-08 09:01:53 - Longitud de la clave hex: 64
2024-11-08 09:01:53 - Longitud de la clave binaria: 32
2024-11-08 09:01:53 - Encriptación exitosa - Longitud datos encriptados: 8212
2024-11-08 09:01:53 - Primeros bytes encriptados (hex): 9b00ea23ba9aabb5ac392c84a3515e85
2024-11-08 09:01:53 - Iniciando encriptación de chunk con parámetros:
2024-11-08 09:01:53 - Longitud del chunk: 8192
(y continua )

script del cliente

async function loadAndPlayAudioStream(retryCount = 0) {
        try {
            window.audioLoading = true;
            const finalAudioUrl = buildAudioUrl(audioUrl, audioSettings.nonce);
            
            const response = await fetch(finalAudioUrl, {
                method: 'GET',
                credentials: 'same-origin',
                headers: {
                    'X-WP-Nonce': audioSettings.nonce,
                    'X-Requested-With': 'XMLHttpRequest',
                    Accept: 'audio/mpeg',
                    Range: 'bytes=0-'
                }
            });
    
            if (!response.ok) {
                throw new Error(`HTTP error! status: ${response.status}`);
            }
    
            const reader = response.body.getReader();
            const iv = response.headers.get('X-Encryption-IV');

            // Ajuste en la línea donde se obtiene contentLength
            const contentLengthHeader = response.headers.get('Content-Length');
            const contentLength = contentLengthHeader ? parseInt(contentLengthHeader) : -1;  // -1 para indicar longitud desconocida

            // Log para revisar el valor obtenido
            console.log(`Content-Length obtenido: ${contentLength}`);

    
            // Array para almacenar los datos desencriptados
            let decryptedChunks = [];
            let receivedLength = 0;
    
            while(true) {
                const {done, value} = await reader.read();
                
                if (done) {
                    console.log('Transmisión completa');
                    break;
                }
    
                // Desencriptar cada chunk individualmente
                if (value && value.length > 0) {
                    let chunkData = value.buffer;
                    if (iv && audioSettings.key) {
                        try {
                            const decryptedChunk = await decryptAudioData(chunkData, iv, audioSettings.key);
                            decryptedChunks.push(new Uint8Array(decryptedChunk));
                        } catch (error) {
                            console.error('Error desencriptando chunk:', error);
                            continue;
                        }
                    }
                    receivedLength += value.length;
                    console.log(`Procesado ${receivedLength} de ${contentLength} bytes`);
                }
            }
    
            // Combinar todos los chunks desencriptados
            let totalLength = decryptedChunks.reduce((acc, chunk) => acc + chunk.length, 0);
            const finalAudioData = new Uint8Array(totalLength);
            let offset = 0;
            
            for (const chunk of decryptedChunks) {
                finalAudioData.set(chunk, offset);
                offset += chunk.length;
            }
    
            console.log('Audio final combinado:', {
                totalLength: finalAudioData.length,
                chunks: decryptedChunks.length
            });
    
            // Crear blob y cargar wavesurfer
            const blobUrl = createAudioBlobUrl(finalAudioData);
            await validateAudio(blobUrl);
    
            const wavesurfer = initWavesurfer(container);
            window.wavesurfers[postId] = wavesurfer;
    
            // Esperar a que wavesurfer esté listo antes de cargar
            await new Promise((resolve) => {
                wavesurfer.once('ready', resolve);
                wavesurfer.load(blobUrl);
            });
    
            handleWaveSurferEvents(wavesurfer, container, postId, blobUrl);
    
        } catch (error) {
            console.error('Error en loadAndPlayAudioStream:', error);
            handleLoadError(error, retryCount, container);
        }
    }

    async function decryptAudioData(arrayBuffer, iv, key) {
        let ivArray, keyArray;
    
        try {
            // Extraer la longitud y los datos encriptados del chunk
            const dataView = new DataView(arrayBuffer);
            const chunkLength = dataView.getUint32(0);
            const encryptedData = arrayBuffer.slice(4);
    
            console.log('Procesando chunk:', {
                totalLength: arrayBuffer.byteLength,
                chunkLength: chunkLength,
                dataLength: encryptedData.byteLength
            });
    
            // Convertir IV y key
            ivArray = Uint8Array.from(atob(iv), c => c.charCodeAt(0));
            keyArray = new Uint8Array(key.match(/.{1,2}/g).map(byte => parseInt(byte, 16)));
    
            // Importar la clave
            const cryptoKey = await crypto.subtle.importKey(
                'raw',
                keyArray.buffer,
                { name: 'AES-CBC', length: 256 },
                false,
                ['decrypt']
            );
    
            // Desencriptar chunk
            const decryptedData = await crypto.subtle.decrypt(
                { name: 'AES-CBC', iv: ivArray },
                cryptoKey,
                encryptedData
            );
    
            return decryptedData;
        } catch (error) {
            console.error('Error en desencriptación de chunk:', error);
            throw error;
        }
    }