Convertir MP3 a MP4 con PHP y FFmpeg (Ejemplo Código)

Usando el wrapper PHP spatie/ffmpeg (paquete composer) para control FFmpeg limpio y orientado a objetos.

Prerrequisitos

  • PHP 8.0+
  • Composer
  • FFmpeg instalado en servidor (ffmpeg -version funciona en CLI).
  • Paquete composer: composer require spatie/ffmpeg

Script Conversión Básico

<?php require 'vendor/autoload.php'; use Spatie\Ffmpeg\Ffmpeg; use Spatie\Ffmpeg\Exception\ConversionFailedException; try { $ffmpeg = Ffmpeg::create(); $output = $ffmpeg->input('/path/to/input.mp3') ->output('/path/to/output.mp4') ->addArguments(['-c:v', 'libx264', '-tune', 'stillimage', '-c:a', 'aac', '-b:a', '192k', '-pix_fmt', 'yuv420p', '-shortest']) ->convert(); echo "Conversión exitosa. Salida: {$output->getPathname()}"; } catch (ConversionFailedException $e) { echo "Conversión falló: {$e->getMessage()}"; // $e->getCommand() para debug } ?> 

Argumentos Clave Explicados

  • -c:v libx264: Codifica vídeo como H.264 (estándar MP4).
  • -tune stillimage: Optimiza para imagen estática (carátula álbum) — archivo diminuto, codificación rápida.
  • -c:a aac -b:a 192k: Re-codifica audio a AAC 192 kbps (estándar MP4).
  • -pix_fmt yuv420p: Asegura compatibilidad amplia reproductores.
  • -shortest: Para cuando termina stream más corto (audio).

Añadir Carátula Álbum (Pista Vídeo)

$ffmpeg->input('/path/to/input.mp3') ->input('/path/to/cover.jpg') ->output('/path/to/output.mp4') ->addArguments([ '-map', '0:a', '-map', '1:v', '-c:v', 'libx264', '-tune', 'stillimage', '-c:a', 'copy', // mantiene audio original '-pix_fmt', 'yuv420p', '-shortest', '-disposition:v', 'attached_pic' // marca como carátula ]) ->convert(); 

Consideraciones Producción

  • Valida rutas: Asegura input existe, dir output escribible.
  • Timeouts: Configura PHP max_execution_time o usa async (cola/worker).
  • Seguridad: Sanitiza nombres archivo; nunca pases input usuario directo a shell.
  • Límites recursos: FFmpeg usa CPU/RAM; monitoriza en hosting compartido.
  • Manejo errores: Captura ConversionFailedException; loguea $e->getCommand().

Alternativa: Symfony Process (Sin Wrapper)

use Symfony\Component\Process\Process; $process = new Process([ 'ffmpeg', '-y', '-i', '/path/to/input.mp3', '-c:v', 'libx264', '-tune', 'stillimage', '-c:a', 'aac', '-b:a', '192k', '-pix_fmt', 'yuv420p', '-shortest', '/path/to/output.mp4' ]); $process->mustRun(); // lanza excepción si falla 

Usa wrapper para mantenibilidad; Process raw para microservicios sin dependencias.