VoD Smooth Streaming en Windows Azure

Para todo aquellos que trabajan con video la capacidad de poder servir videos desde Windows Azure empleando Smooth Streaming es una de las características más esperadas de la plataforma. Se lleva mucho hablando de esta característica, de la posibilidad de poder servir VoDs (Video On Demand) desde el storage directamente usando smooth streaming, pero al menos de momento no lo tenemos, así que hay que buscar alternativas.

En este post intentaré mostrar una forma de poder servidor videos desde Windows Azure empleando Smooth Streaming. Hablaré únicamente de servir videos bajo demanda, si alguien está interesado es poder hacer “Lives” le recomiendo que revise este proyecto de CodePlex; http://azlivestreaming.codeplex.com/

En el ejemplo que muestro a continuación todos los videos codificados para Smooth Streaming los incluyo dentro de un fichero VHD, fichero que posteriormente subo a un Page Blob de Windows Azure Storage.

Luego, lo que hago es desplegar un WebRole que emplea la característica de Drive para mapear este VHD como una unidad de disco y así poder crear un site de IIS que apunte a la unidad. De esta manera es el propio IIS el que sirve los ficheros como si éstos estuvieran en local.

Los ficheros los pongo en un VHD por si quiero que éstos se compartan por diferentes instancias del Role o por si en un momento dado me interesa que la aplicación sea capaz de ir actualizando los VoDs que se sirven, por ejemplo, porque el usuario puede subir videos.

El fichero VHD se puede crear desde el administrador de discos.

VoD

En el proceso de creación del VHD hay que tener en cuenta los siguientes aspectos:

  • El tamaño del disco tiene que estar entre 16Mb y 1 TB.
  • Tiene que tener formato NTFS.
  • El disco tiene que ser de formato fijo.
  • El fichero VHD generado tiene que subirse como un Page Blob.
  • Si hay varias instancias, hay que tener en cuenta que sólo 1 de ellas puede tener la unidad montada en modo escritura. En lectura pueda haber todos los que se quieran.

Una vez creado, se verá éste como una unidad más del equipo local. Dentro de esta unidad hay que los videos que se quieran. Además de los videos también se deben configurar las políticas para que éstos videos puedan ser consumidos desde dominios diferentes al actual. En el ejemplo que estoy realizando tengo dos sites; uno contendrá el player y otro servirá los videos, de ahí que se necesite permitir las llamadas desde un dominio a otro.

VoD1

Una vez copiados los ficheros, también desde el administrador de discos hay que realizar la acción “detach VHD” para quitar la unidad del VHD y así liberarlo para copiarlo a Storage. Recuerda que tiene que ser un Page Block.

Una vez tengo el VHD, el siguiente paso es crear un nuevo proyecto de Windows Azure, al que añado un WebRole. Del proyecto asociado al WebRole se pueden eliminar todos los ficheros, salvo el web.config.

Lo que sí hay que añadir es el player que se quiere emplear para ver los videos. Se puede emplear cualquier player que sea capaz de ver videos en smooth streaming. Yo por ejemplo que cogido uno hecho en Silverlight que viene con Expression Encoder.

En el player hay que indicar la URL del video que se quiere visualizar: http://servicename.cloudapp.net:8080/VideoSample/VideoSample.ism/manifest

Pongo 8080, porque éste será el puerto que empleará el site que servirá los videos y que apunte al contenido del VHD. VideoSample es un directorio que existe dentro del VHD y que contiene el video.

El siguiente paso será mapear el VHD como una unidad, acción que la incluiré dentro del evento OnStart del WebRole.

private string CreateDrive() { CloudStorageAccount storageAccount = CloudStorageAccount.FromConfigurationSetting("StorageAccount"); LocalResource localCache = RoleEnvironment.GetLocalResource("InstanceDriveCache"); CloudDrive.InitializeCache(localCache.RootPath, localCache.MaximumSizeInMegabytes); // blogUri => http://storagename.blob.core.windows.net/vod/myvhd.vhd string blogUri = RoleEnvironment.GetConfigurationSettingValue("VHDUri"); CloudDrive drive = new CloudDrive(new Uri(blogUri), storageAccount.Credentials); try { drive.Create(20); } catch (CloudDriveException ex) { // handle exception here // exception is also thrown if all is well but the drive already exists } return drive.Mount(localCache.MaximumSizeInMegabytes, DriveMountOptions.None); }

El código anterior lo que hace es montar una unidad de disco a partir de un fichero VHD de 20Mb, un fichero que está en el storage dentro un contenedor llamado vhd. También emplea una caché local, para lo cuál es necesario configurar en el rol un storage local que almacene dicha caché.

VoD2

Una vez se tiene la unidad mapeada, el siguiente paso crear un nuevo site, también en el método OnStart, que apunte a la unidad de disco recién mapeada. Este site se crea en el puerto 8080, en el mismo binding que el site por defecto que está en el puerto 80.

private void CreateNewSiteForVod(string siteRoot) { if (String.IsNullOrEmpty(siteRoot)) return; if (!siteRoot.EndsWith("\")) siteRoot += "\"; var webApplicationProjectName = "Web"; using (ServerManager serverManager = new ServerManager()) { if (!serverManager.Sites.Where(s => s.Name.Equals("VoDSite", StringComparison.OrdinalIgnoreCase)).Any()) { ApplicationPool applicationPool = serverManager.ApplicationPools.Add("VoDSitePool"); applicationPool.AutoStart = true; applicationPool.ManagedPipelineMode = ManagedPipelineMode.Integrated; applicationPool.ManagedRuntimeVersion = "v4.0"; applicationPool.ProcessModel.IdentityType = ProcessModelIdentityType.ApplicationPoolIdentity; string binding = "*:8080:"; int defaultPort = 80; if (serverManager.Sites[RoleEnvironment.CurrentRoleInstance.Id + "_" + webApplicationProjectName].Bindings.Where(b => b.EndPoint.Port == defaultPort).Any()) { binding = String.Format("{0}:8080:", serverManager.Sites[RoleEnvironment.CurrentRoleInstance.Id + "_" + "Web"].Bindings.Where(b => b.EndPoint.Port == defaultPort).First().EndPoint.Address); } Site site = serverManager.Sites.Add("VoDSite", "http", binding, siteRoot); site.Applications.First().ApplicationPoolName = "VoDSitePool"; site.ServerAutoStart = true; serverManager.CommitChanges(); } } }

El método OnStart tendrá el siguiente aspecto:

public override bool OnStart() { CloudStorageAccount.SetConfigurationSettingPublisher((configName, configSetter) => { if (RoleEnvironment.IsAvailable) configSetter(RoleEnvironment.GetConfigurationSettingValue(configName)); else configSetter(ConfigurationManager.AppSettings[configName]); }); string driveLetter = CreateDrive(); CreateNewSiteForVod(driveLetter); return base.OnStart(); }

Ý para terminar, hay que hacer un último paso para instalar IIS Media Services cuando se despliegue la aplicación en Windows Azure, ya que este componente es necesario para poder servir ficheros usando smooth streaming. Para eso podemos usar un Startup Task.

Para ello hay que añadir al proyecto del WebRole el instalador de IISMediaServices y un fichero “.cmd”, indicando en los dos ficheros la opción “Copy Local = true”, para que éstos se incluyan en el despliegue.

Desde el fichero de definición del servicio añadiremos la configuración para que el contenido del cmd se ejecuta al inicializar la instancia.

<Startup> <Task commandLine="setup.cmd" executionContext="elevated"> <Environment> <Variable name="EMULATED"> <RoleInstanceValue xpath="/RoleEnvironment/Deployment/@emulated" /> </Variable> </Environment> </Task> </Startup>

 

Y en el cmd sólo hay que añadir la línea de comandos que instala de manera silenciosa IIS Media Services:

if "%EMULATED%"=="true" goto :EOF msiexec /i IISMedia64.msi /qn

VoD3

Y ya está, ya sólo es necesario desplegar la aplicación en Windows Azure y probar que todo funciona!!

En mi caso http://servicename.cloudapp.net/SmoothStreamingPlayer.html que lo que hace es mostrar un player silverlight que consume un video que se sirve de http://servicename.cloudapp.net:8080

Si os conectáis por RDP a la instancia podréis ver que la máquina tiene dos sites y que uno de ellos apunta a una unidad de disco dónde se ve el contenido del VHD que se ha subido previamente al Storage.

Ibon Landa

bon Landa lleva más de 15 años dedicado al desarrollo de software. Durante este tiempo ha trabajado en diferentes empresas en las cuáles ha podido trabajar en diferentes entornos y tecnologías. Actualmente está focalizado principalmente en tareas de desarrollo, arquitectura, en las herramientas del ciclo de vida y en todo lo relacionado con la plataforma de Cloud Computing Microsoft Azure, área en el que ha sido reconocido como MVP. Participa de forma activa en la comunidad, escribiendo su blog, manteniendo un portal sobre Microsoft Azure y colaborando con Microsoft y grupos de usuarios en eventos de formación, talleres y giras de producto.

3 comentarios en “VoD Smooth Streaming en Windows Azure”

  1. Hola Ibon,
    Muy interesante el artículo, gracias por compartirlo.

    Hay algo que me llama la atención y es que comentas que el usuario podría subir vídeos al VHD, ¿Me podría dar información sobre como hacer esto? he estado buscando como lograr que desde una app de escritorio se puedan subir datos al vhd que será leído desde una aplicación web.

    Saludos!

  2. Hola,

    En el ejemplo que menciono sería un servicio WCF desplegado en un rol el que recibiría los videos del usuario y actualizaría el VHD, no lo actualiza directamente.

    Un saludo,

  3. Hola de nuevo,

    He conseguido crear un servicio que suba/descargue ficheros a un VHD, mi duda ahora es como puedo leer ese vhd desde otro rol que esta en otro servicio hospedado.

    He estado investigando y encontré que se puede montar un snapshot del vhd que es de solo léctura, mi problema con esto es que si se sube un nuevo video hay que crear otro snapshot y eliminar el antiguo que en teoría esta siendo usado por una aplicación.

    Otra forma que encontré era compartir el vhd mediante SMB, pero si no lo he entendido mal esto solo funciona con roles dentro del mismo servicio hospedado.

    ¿Me podrías indicar si hay alguna otra forma de poder lerr el vhd desde cualquier aplicación que tenga en azure?

    Saludos.

Responder a camaya Cancelar respuesta

Tu dirección de correo electrónico no será publicada. Los campos obligatorios están marcados con *