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_GROUP
Para 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 Pod
El 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=key
Esta 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: 80
Nota: 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 up
Y 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/.m3u8
Para 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/archive
El código del ejemplo lo tienes en mi GitHub.
¡Saludos!