La semana pasada compartí contigo cómo configurar Unified Streaming Platform para servir video bajo demanda. En este artículo me gustaría contarte cómo desplegar Unified Streaming para Live en Microsoft Azure, ya que la configuración es algo distinta.
Crear un clúster en AKS y un Azure Disk
Al igual que en el escenario anterior, vamos a utilizar Azure Kubernetes Service para hospedar punto de publicación que utilizaremos para la ingesta y el playout del live. Si todavía no tienes un clúster creado puedes montar uno fácilmente siguiendo estos comandos:
#Variables
RESOURCE_GROUP="usp-live-origin"
LOCATION="northeurope"
AKS_NAME="usp-live-origin-cluster"
#Create resource group
az group create -n $RESOURCE_GROUP -l $LOCATION
# Create AKS cluster
az aks create -n $AKS_NAME -g $RESOURCE_GROUP --node-count 1 --generate-ssh-keys
#Get the context for the new AKS
az aks get-credentials -n $AKS_NAME -g $RESOURCE_GROUPPara el escenario de Live no es recomendable el uso de carpetas compartidas, como usamos en la parte de VoD. En este caso debemos utilizar Azure Disk como volumen persistente, ya que además no es necesario el compartir el punto de montaje entre varios pods. Para ello puedes utilizar los siguientes comandos, para recuperar el grupo de recursos donde tu clúster está alojando el resto de los recursos y para crear uno nuevo del tipo Azure Disk.
#Get the node resource group
NODE_RESOURCE_GROUP=$(az aks show --resource-group $RESOURCE_GROUP --name $AKS_NAME --query nodeResourceGroup -o tsv)
#Create an Azure Disk in the node resource group
az disk create -g $NODE_RESOURCE_GROUP -n live-origin-assets --size-gb 500 --query id --output tsv
#The result, the disk URI, should be used to mount this volume in the PodEl resultado del último comando nos dará la URI que debemos utilizar en la configuración de nuestro pod.
StatefulSet para el despliegue del pod
Para este escenario haremos uso del recurso StatefulSet y un Service que nos proporcionará la IP pública para realizar la ingesta y consumir el directo. Antes de crearlos necesitas un secreto con la clave de Unified Streaming, en mi caso almacenada en un archivo llamado key:
#Create a secret with the USP Key
kubectl create secret generic live-origin-test-license-key --from-file=keyEsta sería la configuración para el recurso StatefulSet:
apiVersion: apps/v1
kind: StatefulSet
metadata:
name: live-origin-test
spec:
replicas: 1
serviceName: live-origin-test
selector:
matchLabels:
name: live-origin
template:
metadata:
labels:
name: live-origin
spec:
containers:
- name: live-origin
image: unifiedstreaming/live:latest
imagePullPolicy: Always
ports:
- name: http
containerPort: 80
protocol: TCP
livenessProbe:
httpGet:
path: /test/test.isml/state
port: http
readinessProbe:
httpGet:
path: /test/test.isml/state
port: http
startupProbe:
httpGet:
path: /test/test.isml/state
port: http
failureThreshold: 60
periodSeconds: 10
resources: {}
env:
- name: USP_LICENSE_KEY
valueFrom:
secretKeyRef:
name: live-origin-test-license-key
key: key
- name: CHANNEL
value: test
- name: PUB_POINT_OPTS
value: --archiving=1 --archive_length=3600 --archive_segment_length=1800 --dvr_window_length=30 --restart_on_encoder_reconnect --mpd.min_buffer_time=48/25 --mpd.suggested_presentation_delay=48/25 --hls.minimum_fragment_length=48/25 --mpd.minimum_fragment_length=48/25 --mpd.segment_template=time --hls.client_manifest_version=4 --hls.fmp4 --iss.minimum_fragment_length=48/25 --hds.minimum_fragment_length=48/25
volumeMounts:
- name: test
mountPath: /var/www/live/test/
volumes:
- name: test
azureDisk:
kind: Managed
diskURI: /subscriptions/YOUR_SUBSCRIPTION_ID/resourceGroups/MC_usp-live-origin_usp-live-origin-cluster_northeurope/providers/Microsoft.Compute/disks/live-origin-assets
diskName: live-origin-assets
Como ves, la imagen a utilizar es unifiedstreaming/live:latest, la cual ya está preconfigurada para el modo live. Es importante definir las variables de entorno, donde USP_LICENCE_KEY cogerá el valor del secreto creado anteriormente, el nombre del canal a través de CHANNEL y PUB_POINT_OPTS que son todas las opciones que estamos habilitando para este entorno de pruebas. Puedes obtener más información sobre todas ellas aquí. Por último, montamos el path /var/www/live/test utilizando el Azure Disk que has creado, utilizando la URI que devolvió el comando tras su creación y el nombre del disco, que en este ejemplo es live-origin-assets.
Por otro lado, este sería el servicio de tipo Load Balancer, para que AKS nos proporcione una IP pública:
apiVersion: v1
kind: Service
metadata:
name: live-origin-test
spec:
type: LoadBalancer
selector:
name: live-origin
ports:
- protocol: TCP
port: 80
targetPort: 80Nota: Este no es el escenario recomendado para un entorno productivo, pero nos sirve para la prueba que estamos realizando ahora mismo.
Para crear ambos recursos, si has descargado el código de mi GitHub puedes hacerlo utilizando este comando:
kubectl apply -f .Ahora ya tienes todo listo para comenzar a ingestar el contenido que quieres transmitir en directo.
Ingesta de contenido
Para hacer un ejemplo sencillo, nuestros amigos de Unified Streaming Platform han puesto a nuestra disposición este repositorio que permite la ingesta del siguiente contenido:

Este nos permite ver sobre todo el retardo en el Live de una forma súper clara. En mi ejemplo, para ejecutarlo contra mi entorno en AKS me he descargado el código y he modificado el archivo docker-compose.yaml de la siguiente manera:
version: "2.1"
services:
# live-origin:
# image: unifiedstreaming/live:latest
# ports:
# - 80:80
# environment:
# - USP_LICENSE_KEY
# - CHANNEL=test
# - LOG_LEVEL=warn
# - PUB_POINT_OPTS=--archiving=1 --archive_length=3600 --archive_segment_length=1800 --dvr_window_length=30 --restart_on_encoder_reconnect --mpd.min_buffer_time=48/25 --mpd.suggested_presentation_delay=48/25 --hls.minimum_fragment_length=48/25 --mpd.minimum_fragment_length=48/25 --mpd.segment_template=time --hls.client_manifest_version=4 --hls.fmp4
# healthcheck:
# test: kill -0 1
# interval: 2s
# timeout: 5s
# retries: 30
ffmpeg-1:
build: ffmpeg
environment:
- PUB_POINT_URI=http://<AKS_SERVICE_PUBLIC_IP>/test/test.isml
- 'TRACKS={ "video": [ { "width": 1024, "height": 576, "bitrate": "500k", "codec": "libx264", "framerate": 25, "gop": 24, "timescale": 50 }, { "width": 1280, "height": 720, "bitrate": "1000k", "codec": "libx264", "framerate": 50, "gop": 48, "timescale": 50 } ], "audio": [ { "samplerate": 48000, "bitrate": "64k", "codec": "aac", "language": "eng", "timescale": 48000 }, { "samplerate": 48000, "bitrate": "64k", "codec": "aac", "language": "dut", "timescale": 48000 } ] }'
# depends_on:
# live-origin:
# condition: service_healthy
# ffmpeg-2:
# build: ffmpeg
# environment:
# - PUB_POINT_URI=http://live-origin/test/test.isml
# - 'TRACKS={ "video": [ { "width": 1024, "height": 576, "bitrate": "500k", "codec": "libx264", "framerate": 25, "gop": 24, "timescale": 50 }, { "width": 1280, "height": 720, "bitrate": "1000k", "codec": "libx264", "framerate": 50, "gop": 48, "timescale": 50 } ], "audio": [ { "samplerate": 48000, "bitrate": "64k", "codec": "aac", "language": "eng", "timescale": 48000 }, { "samplerate": 48000, "bitrate": "64k", "codec": "aac", "language": "dut", "timescale": 48000 } ] }'
# depends_on:
# live-origin:
# condition: service_healthy
De esta forma apunto a mi entorno en AKS y no al live-origin que originalmente viene con ese entorno de pruebas. Para ejecutarlo basta que utilices el siguiente comando (necesitas tener Docker instalado en local):
docker-compose upY si todo ha ido bien deberías de ver la siguiente salida:

A partir de este momento tu despliegue de USP Live en AKS ya está recibiendo video para la retransmisión en vivo.
Cómo probarlo
Para probar DASH y HLS puedes hacer uso de ffplay ejecutando estos dos comandos:
#MPEG-DASH
ffplay http://<AKS_SERVICE_PUBLIC_IP>:80/test/test.isml/.mpd
#Apple's HLS
ffplay http://<AKS_SERVICE_PUBLIC_IP>:80/test/test.isml/.m3u8Para Smooth Streaming puedes usar este otro enlace: http://reference.dashif.org/dash.js/v3.2.2/samples/dash-if-reference-player/index.html?url=http://AKS_SERVICE_PUBLIC_IP/test/test.isml/Manifest
Además, tienes tres endpoints para hacer consultas relacionadas con esta publicación:
#State of the publishing endpoint
curl http://<AKS_SERVICE_PUBLIC_IP>/test/test.isml/state
#Stadistics
curl http://<AKS_SERVICE_PUBLIC_IP>/test/test.isml/statistics
#Archive
curl http://<AKS_SERVICE_PUBLIC_IP>/test/test.isml/archiveEl código del ejemplo lo tienes en mi GitHub.
¡Saludos!

Concepto bonito, pero solo en papel, ponlo en produccion con la ingesta de un evento deportivo y me cuentas cuanto tiempo pasa antes de que se quede todo colgado. No tienes en cuenta que la transcodificacion, y la paquetizacion del video en 3 perfiles y 3 formatos distintos requiere potencia de CPU o GPU. Si todo fuera tan facil y lo solucionaras todo con clusteres de k8s y ffmpeg, se iban a morir de hambre empresas como Teleste, Elemental, Hayvision, etc… Los desarrolladores os creeis que con docker, un poco de codigo y servicios de cloud podeis dar soluciones para todo.
Hola @disqus_iZ51yPiH61:disqus ,
Muchas gracias tu comentario, aunque lamento el tono del mismo, creo que es innecesario.
En primer lugar, creo que no has leído el artículo con detenimiento ya que la parte de ffmpeg se está utilizando única y exclusivamente para la prueba de un evento, después de configurar Unified Streaming en Kubernetes.
En segundo lugar, la mayoría de las empresas que mencionas a día de hoy usan Kubernetes para su despliegue en las diferentes nubes, donde puedes tener configurada cualquier tipo de máquina, incluso con GPU como hacías mención en tu comentario, diferentes discos, cores, memoria, etc., por lo que no está suponiendo los problemas que argumentas. Elemental es propiedad de AWS y desconozco qué utilizan por debajo para ejecutarlo, pero Haivision usa Kubernetes en su solución LightFlow, Harmonic también usa Kubernetes, Bitmovin tiene su propia propuesta de contenerización de sus encoders (y comentan que los suyos propios, los manejados, están contenerizados), MediaKind lo mismo (me lo presentaron justamente esta semana), Unified Streaming Platform tiene su entornos también en Kubernetes, MediaExcel tiene sus encoders corriendo en la misma tecnología… Como te decía, creo que el tono ha sido desafortunado, pero estas empresas para nada se están muriendo de hambre, están aprovechando estas tecnologías igual que el resto y he tenido la oportunidad de trabajar en mayor y menor medida con todas ellas, y no es como tú mencionas.
Comentarte además que Unified Streaming Platform es una de esas empresas que se dedican al mundo media y el contenido de este artículo está consensuado con el equipo técnico de ellos, ya que este está basado en una prueba de concepto en la que tuvimos que trabajar conjuntamente.
¡Saludos!