Introducción
La semana pasada estuve con un diario local que quiere hacer live streaming si hacer una gran inversión inicial porque no saben cómo van a rentabilizar ese nuevo canal que están desarrollando. Este requerimiento de inversión baja para partir calza perfecto con el comportamiento de costos de las soluciones de Nube. En una solución tradicional, en el Datacenter del cliente, tienen que comprar los servidores que van a necesitar desde el día cero, mientras que en la nube pagaran solo por lo que usan.
En Windows Azure, solución de Nube de Microsoft, existe un servicio llamado Windows Azure Media Services, el cual permite hacer On Demand Streming pero al día de hoy no está disponible para clientes la funcionalidad de Live Streming.
Como Azure es una plataforma, y no un producto, las empresas pueden armar soluciones utilizando las piezas base de la plataforma como si fuera un Lego. En este sentido, podemos armar un servicio de Live Streaming.
Como Azure es una plataforma, y no un producto, las empresas pueden armar soluciones utilizando las piezas base de la plataforma como si fuera un Lego. En este sentido, podemos armar un servicio de Live Streaming.
Existe un proyecto en codeplex llamado Windows Azure Live Smooth Streaming de DmitriMartynov que implementa el servicio de IIS Media Services 4 de manera automática en un Web Role utilizando las posibilidades de automatización de tareas en el inicio del role. Es un excelente proyecto!
El proyecto soporta dos modos de despliegue, todo en un solo rol o multi instancias. En la primera opción, el servidor de origen (el que recibe el video desde la fuente) y el servidor de distribución son el mismo. La segunda opción, de una implementación distribuida, el servidor de origen y el de distribución son diferentes y además se podría tener varias instancias de distribución.
En mi opinión, la implementación todo en uno, funciona bien para pequeñas implementaciones. Ahora, el modelo que se propone para multiroles, tiene un detalle que afecta el desempeño y que puede ser mejorado. La arquitectura propuesta por DmitriMartynov es siguiente.
Las observaciones que tengo de la solución son básicamente dos. Primero, una oportunidad de mejora que tiene que ver con el comportamiento de Windows Azure. La comunicación entre el rol que llaman en el diagrama upstream con el dwonstream se hace a través del endpoint público. Esto trae como consecuencia que la comunicación “sale” de la red internar y pasa por el balanceador de carca de cada Cloud Services donde se hospeda cada servicio. Yo utilizaría una red virtual entre los dos Cloud Services para tener comunicación directa entre los diferentes servicios. La utilización de una red virtual tiene múltiples ventajas de performance ya que por ejemplo, todos los recursos están en el mismo Affinity Groups, la comunicación es interna sin pasar por los balanceadores y la VIP, etc.
Segundo, esta es una observación de IIS Media Service, en vez de hacer PULL desde los servidores de distribución al origen se puede hacer que el origen haga push a los servidores de distribución, y así dejar a los servidores de distribución con la única responsabilidad de entender clientes finales. El siguiente diagrama muestra mis propuestas.
Ahora, vamos a ver como configurar el escenario propuesto en este post.
Configuración de la red virtual en Windows Azure
La creación de una red virtual se puede realizar siguiendo el asistente del sitio de administración de Azure. Para este caso, vamos a utilizar el asistente de una creación personalizada. En el primer paso nos pide el nombre de la red virtual y el grupo de afinidad. El grupo de afinidad es clave ya que le indica al datacenter que todos los recursos que están afiliados a ese grupo trabajan juntos por lo cual deben ser desplegados lo más cerca posible para disminuir la latencia de comunicaciones entre ellos.
En el paso dos, nos preguntan sobre si usaremos un DNS propio, si tendremos VPN site to site y point to site. En este caso, no necesitamos nada de esto por lo que avanzamos al paso 3.
En el tercer paso, tenemos la definición del direccionamiento y las sub redes. Este es el paso principal de configuración para nuestra solución. Aquí definimos básicamente dos segmentos, uno para el servidor de origen (UpStream) es decir el servidor que recibe el video desde la fuente y otro para los servidores de distribución (DownStream).
Proyecto Cloud
Ahora que tenemos la red Virtual lista en Azure, pasamos a desarrollar el cloud en Visual Studio. La idea es crear 2 Cloud services, Upream y DownStream. El primero solo tendrá una instancia de un Web Role que tendrá el punto de publicación PUSH para recibir el viedo desde la fuente codificada. Este Web Role tiene la siguiente definición de servicio, la cual se refleja en el archivo ServiceDefinition.csdef. En este xml podemos ver que tiene 1 instancia y en EndPoint público llamado “push” en el puerto 8080.
<?xml version="1.0" encoding="utf-8"?> <ServiceDefinition name="waUpStream" xmlns="http://schemas.microsoft.com/ServiceHosting/2008/10/ServiceDefinition" schemaVersion="2013-03.2.0"> <WebRole name="upStream" vmsize="Medium"> <Sites> <Site name="Web"> <Bindings> <Binding name="Endpoint1" endpointName="push" /> </Bindings> </Site> </Sites> <Endpoints> <InputEndpoint name="push" protocol="http" port="8080" /> </Endpoints> <Imports> <Import moduleName="Diagnostics" /> <Import moduleName="RemoteAccess" /> <Import moduleName="RemoteForwarder" /> </Imports> <Startup> <Task commandLine="startup.cmd" executionContext="elevated"> </Task> </Startup> </WebRole> </ServiceDefinition>
Junto a lo anterior, aquí se define la tarea de configuración de IIS Media Services. La idea es que cuando este rol se inicie, se instale IIS Media Services de manera automática como buena aplicación PaaaS. Para ellos, se ejecuta la línea de comando llamada “startup.cmd”con privilegios elevados porque realizará instalaciones den el servidor. El archivo cmd es el siguiente y realiza la instalación por línea de comando.
set msiexec=%systemroot%\system32\msiexec.exe set appcmd=%systemroot%\system32\inetsrv\appcmd.exe %msiexec% /i "%~dp0\IISMedia64.msi" /qn ADDLOCAL=ALL /Le startup_media.txt
Junto a lo anterior, aquí se define la tarea de configuración de IIS Media Services. La idea es que cuando este rol se inicie, se instale IIS Media Services de manera automática como buena aplicación PaaaS. Para ellos, se ejecuta la línea de comando llamada “startup.cmd”con privilegios elevados porque realizará instalaciones den el servidor. El archivo cmd es el siguiente y realiza la instalación por línea de comando.
Después de la definición del servicio, debemos hacer la configuración del servicio la que se ve reflejada en el archivo ServiceConfiguration.Cloud.cscfg. En este archivo podemos ver que el rol solo tendrá una instancia lo que es lógico. Ahora, aquí es donde podemos definir que este Cloud Service utilizará la red virtual creada en el paso anterior. Esto se configura en el nodo llamado NetworkConfiguration, donde le indicamos la subnet en que el rol será desplegado.
<?xml version="1.0" encoding="utf-8"?> <ServiceConfiguration serviceName="waUpStream" xmlns="http://schemas.microsoft.com/ServiceHosting/2008/10/ServiceConfiguration" osFamily="3" osVersion="*" schemaVersion="2013-03.2.0"> <Role name="upStream"> <Instances count="1" /> <ConfigurationSettings> </ConfigurationSettings> <Certificates> <Certificate name="Microsoft.WindowsAzure.Plugins.RemoteAccess.PasswordEncryption" thumbprint="0DA151D90DD3C3B707595B898EAB5F53ED5609EF" thumbprintAlgorithm="sha1" /> </Certificates> </Role> <NetworkConfiguration> <VirtualNetworkSite name="vnFrontBack" /> <AddressAssignments> <InstanceAddress roleName="upStream"> <Subnets> <Subnet name="BackEnd" /> </Subnets> </InstanceAddress> </AddressAssignments> </NetworkConfiguration> </ServiceConfiguration>
Creación del punto de publicación PUSH de UpStream
Una vez creado y configurado el Cloud Services, debemos crear en el Web Role un punto de publicación del tipo push. Para eso creamos un archivo XML llamado push.isml y agregamos en el mismo los servidores de distribución en el TAG body/par. De esta forma el contenido que el servidor de recibe desde el origine, lo publica en los servidores de distribución.
<?xml version="1.0" encoding="utf-8"?> <smil xmlns="http://www.w3.org/2001/SMIL20/Language"> <head> <meta name="title" content="Punto de Push para Live Streaming" /> <meta name="module" content="liveSmoothStreaming" /> <meta name="sourceType" content="Push" /> <meta name="publishing" content="Fragments;Streams;Archives" /> <meta name="estimatedTime" content="0" /> <meta name="lookaheadChunks" content="2" /> <meta name="manifestWindowLength" content="0" /> <meta name="startOnFirstRequest" content="True" /> <meta name="archiveSegmentLength" content="0" /> <meta name="formats" content="m3u8-aapl" /> <meta name="m3u8-aapl-segmentlength" content="10" /> <meta name="m3u8-aapl-maxbitrate" content="3000000" /> <meta name="m3u8-aapl-allowcaching" content="False" /> <meta name="m3u8-aapl-backwardcompatible" content="False" /> <meta name="m3u8-aapl-enableencryption" content="False" /> <meta name="filters" content="" /> <meta name="restartOnEncoderReconnect" content="true" /> </head> <body> <par> <ref src="http://10.0.0.4/push.isml" /> <ref src="http://10.0.0.5/push.isml" /> <ref src="http://10.0.0.6/push.isml" /> </par> </body> </smil>
Ya que estamos usando redes virtuales podemos conocer de antemano las direcciones IP que utilizarán los servidores de distribución, basados en el direccionamiento del segmento en el cual son desplegados. En mi caso estoy usando este direccionamiento y los servidores de distribución estarán en la subred llamada BackEnd. El direccionamiento para máquinas de ese segmento comienza en 10.0.0.4 y termina en 10.0.0.6
Con esto tenemos completo nuestro servicio upStream para que el orignen haga push del contenido desde la estación de codificación a la Nube.
Los elementos del proyecto Upstream los podemos ver en la siguiente figura. Tenemos el proyecto Web llamado upStream y el proyecto Cloud Services llamado waUpStream. El primero tiene el instalador de IIS Media Services, el punto de publicación Push.isml y el script inicial de configuración startup.cmd.
Configuración de downStream
Ahora vamos a revisar la definición de servicio de del Cloud Services waDownStream que se encuentra en el archivo ServiceDefinition.csdef. El objetivo de este Cloud Service es recibir la copia push desde el servidor de origen y ponerla a disposición de los clientes finales mediante una granja de servidores, como aparece en la imagen 2 Arquitectura propuesta. En la definición se crea en EndPoint llamado www en el puerto 80, para el acceso de clientes. Además, al igual que en Cloud Service upStream, se crea una tarea de inicio que ejecuta con privilegios elevados el script startup.cmd. Además podemos ver que la instancia en que corre el rol es de tamaño pequeño, ya que aquí apostamos por escalar de manera horizontal, como lo hacen comúnmente los servicios PaaS.
<?xml version="1.0" encoding="utf-8"?> <ServiceDefinition name="waDownStream" xmlns="http://schemas.microsoft.com/ServiceHosting/2008/10/ServiceDefinition" schemaVersion="2013-03.2.0"> <WebRole name="downStream" vmsize="Small"> <Sites> <Site name="Web"> <Bindings> <Binding name="Endpoint1" endpointName="www" /> </Bindings> </Site> </Sites> <Endpoints> <InputEndpoint name="www" protocol="http" port="80" /> </Endpoints> <Imports> <Import moduleName="RemoteAccess" /> <Import moduleName="RemoteForwarder" /> </Imports> <Startup> <Task commandLine="startup.cmd" executionContext="elevated"> </Task> </Startup> </WebRole> </ServiceDefinition>
Una vez definido el servicio hay que configurarlo. El archivo ServiceConfiguration.Cloud.cscfg nos muestra que este servicio corre en 3 instancias y que el Cloud Service se conecta a la red Virtual vnFrontBack en la sub red FrontEnd.
<?xml version="1.0" encoding="utf-8"?> <ServiceConfiguration serviceName="waDownStream" xmlns="http://schemas.microsoft.com/ServiceHosting/2008/10/ServiceConfiguration" osFamily="3" osVersion="*" schemaVersion="2013-03.2.0"> <Role name="downStream"> <Instances count="3" /> <ConfigurationSettings> </ConfigurationSettings> <Certificates> <Certificate name="Microsoft.WindowsAzure.Plugins.RemoteAccess.PasswordEncryption" thumbprint="878C2E5211A054E97146A4FBDEBB61C0FD8F34E4" thumbprintAlgorithm="sha1" /> </Certificates> </Role> <NetworkConfiguration> <VirtualNetworkSite name="vnFrontBack" /> <AddressAssignments> <InstanceAddress roleName="downStream"> <Subnets> <Subnet name="FrontEnd" /> </Subnets> </InstanceAddress> </AddressAssignments> </NetworkConfiguration> </ServiceConfiguration>
El proyecto web de este Cloud Service se llama downStream. Este proyecto contiene un punto de publicación llamado push.isml, que a diferencia del punto de publicación de upStream, este no distribuye el contenido a otros servidores.
<?xml version="1.0" encoding="utf-8"?> <smil xmlns="http://www.w3.org/2001/SMIL20/Language"> <head> <meta name="title" content="Look Point" /> <meta name="module" content="liveSmoothStreaming" /> <meta name="sourceType" content="Push" /> <meta name="publishing" content="Fragments;Streams;Archives" /> <meta name="estimatedTime" content="0" /> <meta name="lookaheadChunks" content="2" /> <meta name="manifestWindowLength" content="0" /> <meta name="startOnFirstRequest" content="True" /> <meta name="archiveSegmentLength" content="0" /> <meta name="formats" content="m3u8-aapl" /> <meta name="m3u8-aapl-segmentlength" content="10" /> <meta name="m3u8-aapl-maxbitrate" content="3000000" /> <meta name="m3u8-aapl-allowcaching" content="False" /> <meta name="m3u8-aapl-backwardcompatible" content="False" /> <meta name="m3u8-aapl-enableencryption" content="False" /> <meta name="filters" content="" /> <meta name="restartOnEncoderReconnect" content="true" /> </head> <body> </body> </smil>
Ahora, debemos publicar una página web donde instalar nuestro control de Silverligth SmoothStreamingPlayer.xap para que la gente vea el Streaming. La página se llama default.aspx. El siguiente código muestra el objeto incrustado en el HTML.
Junto con el video, en esta página se muestra el nombre de la instancia de servidor a la cual nos conectamos, recordar que esto corre en una granja de servidores, y se muestra la lista de instancias del rol. Para conocer las instancias del role utilizamos el siguiente código.
foreach (var roleInstance in Microsoft.WindowsAzure.ServiceRuntime.RoleEnvironment.Roles["downStream"].Instances) { blServers.Items.Add(roleInstance.Id); }
Podemos ver el contenido de los proyectos en Solution Explorer como se muestra en la siguiente imagen.
Publicación de los servicios
La publicación de los dos servicios lo realizamos con Visual Studio.
Captura, codificación y publicación del video en vivo
Una vez completado el despliegue podemos comenzar con la captura del video y su publicación en el servidor de originen. Para ellos vamos a utilizar el programa Microsoft Expression Encoder. Al iniciar el programa seleccionamos la opción de proyecto Live Broadcasting.
Ahora, configuramos el tipo de Encode de video para una salida del tipo IIS Smooth Streaming con video H.264 Baseline.
Luego, agregamos la fuente de video con la opción Add Live Source, y seleccionamos la cámara que utilizaremos en la opción Video Device. En mi caso voy a utilizar la WebCam de mi escritorio.
Teniendo definido el tipo de codificación y la fuente de video, debemos definir la salida. Nosotros queremos publicar Live Streaming en un servidor en Windows Azure. Para ellos seleccionamos en la pestaña de configuración Output el checkbox streaming y el radio button Publishing point con el valor de http://jpggupstream.cloudapp.net:8080/push.isml en Location. Por último, para conectarse con el punto de publicación apretar el botón Connect, luego de unos segundos debería ponerse verde y decir Connected.
Para habilitar el botón Start, debes activar la cámara haciendo click en Cue Source. Estamos listos para comenzar a trasmitir! Se inicia la transmisión utilizando el botón Strat y podemos ver los cuadros que estamos codificando.
Ahora, utilizando el browser vamos al sitio Web http://jpggdownstream.cloudapp.net/ y podemos ver el video en vivo.
Con esto completamos el sencillo procedimiento necesario para montar en la nube un servicio de Live Streaming, con separación de roles de servidor de origen y granja de distribución con comunicación por la red interna entre los Cloud Services.
Estimado.
Me puede ayudar a hacer ese mismo escenario.
Saludos.
Hola,
Que necesitas ? Toda la info esta en el post
😉
Tiene muy buena pinta. Estoy intentando hacer algo parecido, pero no quiero utilizar Expression encoder.
Quiero usar la kinect V2 para emitir en directo, pero teniendo en cuenta que cada usuario puede ver su kinect (tendría que haber un servicio para cada kinect?)
He visto que con el siguiente enlace podría conseguirlo: https://channel9.msdn.com/Events/Build/2013/3-549 (min 41 o por ahí), pero no esty muy seguro.
saludos y muchas gracias
Hola,
estuve el año pasado en esa presentación en otro evento.
El servicio de live streaming no está hoy abierto al publico, pero cuando esté podrás usarlo como describes.
JuanPablo
Tengo varias preguntas. Con este post puedo empezar a transmitir desde ya? cuantos usuarios conectados simultáneamente soporta? que costos demandaría?
Hola,
Si puedes comenzar a trasmitir.
La cantidad depende del tamaño de la infraestructura que despliegues.
Los costos también dependen de la infra.
Ahora, en un futuro próximo podrás usar Azure media services para esto, de un modo mucho más simple.