innoboxrr / video-processor
Requires
- pbmedia/laravel-ffmpeg: ^8.3
Requires (Dev)
- innoboxrr/larapack-generator: ^3.2|^4.0
- orchestra/testbench: ^8.14
This package is auto-updated.
Last update: 2025-06-20 14:32:18 UTC
README
CloudFrontService
Perfecto Raúl. A continuación te detallo exactamente qué opciones debes seleccionar al crear una nueva distribución de CloudFront para entregar contenido HLS (.m3u8/.ts) con URLs firmadas usando el sistema moderno (Public Keys y Key Groups).
🧭 PASO A PASO PARA CREAR TU DISTRIBUCIÓN CLOUDFRONT SEGURA
🔹 1. Distribution options
- ✅ Selecciona:
Single website or app
🔹 2. Origin
-
Origin domain: Si tu video está en un bucket S3 privado:
nombre-del-bucket.s3.amazonaws.com
⚠️ Asegúrate de que el bucket esté privado y tengas habilitado CloudFront como método de acceso.
-
Origin path (opcional): Deja vacío, a menos que todos tus videos estén en un subdirectorio como
/videos
. -
Name: Ponle un nombre descriptivo, como
s3-origin-videos
. -
Add custom header: No es necesario.
-
Enable Origin Shield: ❌ No
🔹 3. Default cache behavior
-
Path pattern: Default
(*)
-
Compress objects automatically: ✅
Yes
Viewer
-
Viewer protocol policy: ✅
Redirect HTTP to HTTPS
-
Allowed HTTP methods: ✅
GET, HEAD
(solo necesitas servir archivos) -
Restrict viewer access: ✅
Yes
→ Esto es esencial para usar URLs firmadas.
Cache key and origin requests
-
✅
Cache policy and origin request policy (recommended)
-
Cache policy: Selecciona:
CachingOptimized
-
Origin request policy: Selecciona:
AllViewerExceptHostHeader
o crea uno nuevo si necesitas headers especiales. -
Response headers policy: Opcional. Puedes dejarlo vacío.
-
🔹 4. Function associations
- ❌ No necesitas configurar funciones en este momento.
🔹 5. Web Application Firewall (WAF)
- ✅ Puedes seleccionar
Do not enable
(puedes agregarlo luego si necesitas protección).
🔹 6. Price class
-
✅ Puedes seleccionar según tu público:
Use only North America and Europe
si solo tienes usuarios en esas regionesUse all edge locations
para mejor rendimiento global
🔹 7. Alternate domain name (CNAME) (opcional)
- Si vas a usar un dominio propio, agrégalo aquí (ej.
videos.tudominio.com
) - Si no, deja vacío
🔹 8. Custom SSL certificate
- Si usaste un CNAME, aquí debes seleccionar el certificado SSL desde AWS Certificate Manager.
- Si no tienes uno aún, haz clic en "Request certificate"
El certificado debe estar en la región
us-east-1
(Virginia del Norte).
🔹 9. Supported HTTP versions
- ✅ Marca
HTTP/2
yHTTP/3
(mejora de rendimiento)
🔹 10. Default root object
- ❌ Déjalo vacío (no aplica para contenido HLS)
🔹 11. IPv6
- ✅
On
🔹 12. Standard logging
- ❌
Off
(puedes activarlo después si deseas auditar tráfico)
✅ FINALIZA
Haz clic en Create distribution.
Una vez creada:
- Ve a Behaviors > Edit
- En la sección de seguridad, asocia el Key Group que creaste anteriormente.
kEY MANAGEMENT
1. Genera tu par de claves (privada y pública RSA)
En tu máquina local, corre:
openssl genrsa -out private_key.pem 2048 openssl rsa -pubout -in private_key.pem -out public_key.pem
Esto te dará:
private_key.pem
: la usarás para firmar las URLs.public_key.pem
: la subirás a AWS.
2. Crea la clave pública en AWS
- Ve a CloudFront > Key Management > Public Keys
- Haz clic en "Create public key"
- Ponle un nombre y pega el contenido de
public_key.pem
- Guarda el
ID
de la clave pública (ejemplo:K123ABC456XYZ
)
3. Crea un Key Group
- Ve a CloudFront > Key Groups
- Haz clic en "Create key group"
- Ponle nombre
- Selecciona la clave pública que creaste antes
- Guarda el ID del Key Group (ejemplo:
abcd1234-keygroup
)
4. Asocia el Key Group a tu distribución de CloudFront
- Ve a tu distribución de CloudFront
- En Behaviors > Edit, busca la sección Restrict viewer access (signed URLs or signed cookies)
- Selecciona Yes
- En "Trusted key groups", agrega el Key Group creado
Guarda los cambios.
5. Guarda tu clave privada en Laravel
Guarda private_key.pem
en tu proyecto, por ejemplo en:
storage/cloudfront/private_key.pem
6. Agrega configuración en .env
CLOUDFRONT_DOMAIN=https://tudistribucion.cloudfront.net
CLOUDFRONT_PUBLIC_KEY_ID=K123ABC456XYZ
CLOUDFRONT_PRIVATE_KEY_PATH=storage/cloudfront/private_key.pem
CLOUDFRONT_URL_EXPIRATION=240
7. Agrega la configuración a config/videoprocessor.php
'cloudfront' => [ 'domain' => env('CLOUDFRONT_DOMAIN'), 'public_key_id' => env('CLOUDFRONT_PUBLIC_KEY_ID'), 'private_key_path' => base_path(env('CLOUDFRONT_PRIVATE_KEY_PATH')), 'url_expiration' => env('CLOUDFRONT_URL_EXPIRATION', 240), ],
8. Lógica para generar una URL firmada
Aquí tienes una clase de servicio compatible con el sistema moderno:
use Carbon\Carbon; class ModernCloudFrontService { public function generateSignedUrl(string $resourceUrl): string { $expires = Carbon::now()->addMinutes(config('videoprocessor.cloudfront.url_expiration'))->timestamp; $policy = json_encode([ 'Statement' => [[ 'Resource' => $resourceUrl, 'Condition' => [ 'DateLessThan' => ['AWS:EpochTime' => $expires], ], ]], ]); $privateKey = file_get_contents(config('videoprocessor.cloudfront.private_key_path')); openssl_sign($policy, $signature, $privateKey, OPENSSL_ALGO_SHA1); $encodedPolicy = strtr(base64_encode($policy), ['+' => '-', '=' => '_', '/' => '~']); $encodedSignature = strtr(base64_encode($signature), ['+' => '-', '=' => '_', '/' => '~']); return $resourceUrl . '?Policy=' . $encodedPolicy . '&Signature=' . $encodedSignature . '&Key-Pair-Id=' . config('videoprocessor.cloudfront.public_key_id'); } }
9. Cómo usarla
$service = new ModernCloudFrontService(); $url = $service->generateSignedUrl('https://tudistribucion.cloudfront.net/path/to/video/index.m3u8'); return redirect()->away($url);
✅ Resultado
El sistema generará URLs como:
https://yourcdn.cloudfront.net/video/abc/index.m3u8?Policy=...&Signature=...&Key-Pair-Id=K123ABC456XYZ
Y solo podrán reproducirse si son válidas y no han expirado.
Notificaciones de SNS para el procesamiento de MediaConverter
✅ 1. Crea un SNS Topic en AWS Ve a AWS SNS.
Crea un Topic de tipo Standard.
Dale un nombre (ej. MediaConvertJobNotifications).
Guarda el ARN del topic (lo usarás en MediaConvert).
TODO
- AutoGenerateTranslatedVttRequest & UploadTranslatedVttRequest usan el modelo Language
- No debería ser así, ya que es una acoplamiento con la app principal
- Hacer que el paquete use su propio modelo Video yque tenga un trait para todos los mutators y relaciones
- Ver si este paquete asume el modelo Languaje & Subtitles dentro de su misma estructura.