Windows Azure

Democratizando conteúdo de vídeo com o Windows Azure Media Services

Bruno Terkaly
Ricardo Villalobos

Baixar o código de exemplo

Umas das tendências inequívocas previstas para um crescimento extraordinário nos próximos anos é o streaming de conteúdo de vídeo. De acordo com o Cisco Visual Networking Index (VNI) 2011, o tráfego da Internet relacionado à essa atividade irá quadruplicar até 2015. Diversos fatores estão por detrás deste fenômeno, incluindo: redução dos custos de armazenamento, computação em nuvem e recursos de armazenamento escaláveis, redes de banda larga alta e uma variedade de dispositivos habilitados para vídeo, como tablets e smartphones. Criar, codificar e distribuir vídeo nunca foi mais prático e acessível mesmo para o entusiasta ocasional.

Há uma grande batalha acontecendo sobre a maneira como o conteúdo de vídeo está sendo entregue e protegido por leis de direitos autorais. Muitos de nós testemunhamos a indústria de música passar por uma tremenda transformação, movendo o poder das grandes gravadoras para empresas de mídia baseadas na Internet. As maiores operadoras e provedores a cabo hoje estão preocupados com o crescimento emergente do vídeo sob demanda e o uso de canais da Internet para distribuí-lo, incluindo YouTube, Ustream e justin.tv, para mencionar alguns.

A Microsoft não está de braços cruzados enquanto tudo isso acontece. Em maio de 2012, a empresa de software lançou novos recursos do Media Services no Windows Azure, que ajudarão a democratizar a criação, gerenciamento e entrega de vídeo para as massas. O Windows Azure Media Services (apenas “Media Services” daqui em diante para fins de brevidade) dão suporte a muitos tipos diferentes de dispositivos, de smartphones a tablets a estações de trabalho de vídeo de alta capacidade. Esse conjunto de recursos, anteriormente intitulado Nimbus, permite que desenvolvedores individuais e corporações criem soluções de mídia baseadas em nuvem para ingestão, processamento, gerenciamento e entrega de conteúdo de mídia.

Resolvendo problemas

Esses novos recursos do Media Services fornecem uma solução automatizada, padronizada e econômica para o espaço de gerenciamento de mídia que reduz drasticamente as barreiras e complexidades ao oferecer três benefícios principais:

  1. Escalabilidade automática com o aproveitamento dos benefícios que a computação em nuvem oferece, incluindo o aumento da capacidade sob demanda, com base nas necessidades dos usuários.
  2. Uma interface ricamente programável com base em uma API RESTful, junto com uma biblioteca cliente do Microsoft .NET Framework que permite aos desenvolvedores criar, gerenciar e manter fluxos de trabalho personalizados facilmente.
  3. Um ecossistema parceiro que inclui componentes de diversas empresas que pode ser conectado a qualquer etapa dos fluxos de trabalho supracitados.

Esse Media Services abrangente fornece soluções para uma variedade de problemas comuns de empresas que criam, gerenciam e distribuem conteúdo. O primeiro é custo, pois construir um datacenter compatível com vídeo é caro. Ter de provisionar servidores, codificadores, equipamento de rede e software relacionado representa uma alta barreira para a entrada. O segundo problema que o Media Services resolve é o problema que abrange todo o setor de fluxos de trabalho personalizados. Muitas empresas no segmento de mídia criaram seus próprios contratos comerciais proprietários, o que torna difícil coordenar serviços relacionados por diferentes fornecedores usando diversos formatos e protocolos. Padronizar o modo como o vídeo é processado melhora a coordenação e a produtividade quando você tem diversos participantes envolvidos na criação e gerenciamento do conteúdo.

Padrões abertos

O Media Services é baseado em padrões abertos, significando que ele pode ser aproveitado por quase qualquer cliente, incluindo Java, PHP, Objective-C e jQuery, para mencionar alguns. O pacote completo de recursos está disponível através de uma API RESTful, aproveitando o protocolo OData para ajudar com recursos de consulta flexíveis. Também há um SDK do .NET C#, criado com base na API RESTful, que facilita e simplifica o acesso à estrutura para os desenvolvedores que usam essa linguagem (consulte a Figura 1).

Figura 1 Duas abordagens para se usar programaticamente o Windows Azure Media Services

API REST/OData

Os desenvolvedores podem acessar os componentes do Media Services por meio da camada da API REST (Representational State Transfer). Como o REST é baseado em HTTP, ele pode ser consumido de praticamente qualquer lugar usando uma ampla variedade de linguagens, aplicativos e plataformas. Em resumo, a API REST é a interface universal, pública e programática para acessar a camada do Media Services na Web.

REST é uma estratégia de arquitetura para criar aplicativos de cliente-servidor em rede com base em padrões abertos. REST fornece um protocolo sem monitoração de estado, armazenável e padrão (HTTP) para enviar informações entre computadores em rede.

API .NET

Naturalmente, também há um SDK do .NET Client (que engloba as chamadas da API REST e simplifica o processo de criação de um aplicativo cliente do Media Services baseado em .NET)

Este artigo se concentrará na API .NET. Artigos futuros irão focar abordagens baseadas em REST.

Aproveitando a API do Media Services

A fim de entender melhor os benefícios dos recursos do Media Services do Windows Azure, este artigo se concentra em um cenário de caso específico. Imagine um vídeo caseiro que precisa ser compartilhado com diversos membros da família ou amigos que podem ter uma variedade de dispositivos móveis. A Figura 2 descreve o fluxo de trabalho geral necessário para entregar conteúdo de vídeo processado personalizado ao mundo.

Overall Workflow Required to Distribute Video Content
Figura 2 Fluxo de trabalho geral necessário para distribuir conteúdo de vídeo

Pré-requisitos

Carregando e codificando conteúdo

Vamos começar com as tarefas básicas para distribuição de conteúdo de vídeo. O código na Figura 3 realiza dois objetivos importantes de qualquer pessoa que trabalha com vídeo. O primeiro é carregar o conteúdo original para que ele possa ser processado. O segundo objetivo é codificar realmente o conteúdo de modo que ele possa ser consumido por diversos dispositivos. Há muitos formatos diferentes de vídeo, como MPEG, MPEG-2 (QuickTime), RealMedia, H.264 (MP4) e Windows Media, apenas para mencionar alguns; mesmo o YouTube tem seu próprio formato de codificação. Os formatos de codificação não são iguais. Muitos deles são projetados para ser pequenos, permitindo downloads da Web e renderizações rápidos. Outros, como o H.264, enfatiza a qualidade sem preocupação com o tamanho do vídeo.

Figura 3 Carregando e executando um trabalho de codificação

static void Main(string[] args)
{
  // Part 1 - Connect to Media Services
  //          Setup upload progress event
  //          Upload a video to encode
  CloudMediaContext mediaContext =
    new CloudMediaContext("[ ACCOUNT NAME ]","[ ACCOUNT KEY ]");
  mediaContext.Assets.OnUploadProgress += Assets_OnUploadProgress;
  var asset = mediaContext.Assets.Create(    
    @"C:\windows\Performance\WinSat\winsat.wmv");
  // Part 2 - Create a task, specify encoding details
  Console.Clear();
  IJob job = mediaContext.Jobs.CreateJob("Sample Job");
  var expressionEncoder = mediaContext.MediaProcessors.Where(
    mp => mp.Name == "Expression Encoder").Single();
  var task = job.Tasks.Add(
    mediaProcessor: expressionEncoder,
    configuration: "H.264 HD 720p VBR");
  task.Inputs.Add(asset);
  task.Outputs.Add("Sample Task Output Asset");
  // Part 3 - Submit the encoding job to begin processing
  while (job.State != JobState.Finished)
  {
    job = mediaContext.Jobs.Refresh(job.Id);
    Console.SetCursorPosition(0, 0);
    Console.WriteLine("Job Name: " + job.Name);
    Console.WriteLine("Job ID: " + job.Id);
    Console.WriteLine();
    Console.WriteLine("Job State: {0,-20}", job.State);
    Console.WriteLine("Task Progress: {0:0.00}%  ",
      job.Tasks.Single().Progress);
    Thread.Sleep(500);
  }
  Console.WriteLine();
  Console.WriteLine("Job Complete!");
  Console.ReadLine();
}
// Part 4 - Display completion progress (See Part 1, where the callback was set up)
static void Assets_OnUploadProgress(object sender, 
  UploadProgressEventArgs e)
{
  Console.WriteLine(e.Progress);
}

A Figura 4 explica o código da Figura 3 de acordo com as seções denominadas Parte 1 a Parte 4.

Figura 4 Comentários do código-fonte na Figura 3 (Consulte Partes 1-4)

Parte 1

Esse código realiza três objetivos básicos:

   1. Cria um objeto CloudMediaContext, fornecendo credenciais para autenticação no Media Services. Esse conteúdo é usado em todo o restante do código para gerenciar e processar os ativos de mídia.

  2. Configura o código de retorno de chamada denominado Assets_OnUploadProgress, que é usado para relatar ao usuário a porcentagem de conclusão do processo de carregamento.

  3. Carrega o arquivo de vídeo original (winsat.wmv) para que possa ser processado.

Observação: A terminologia usada aqui é “ativos,” que, nesse caso, se refere ao vídeo original.

Parte 2 O objetivo desse código é criar uma tarefa, que é composta de um processador de mídia, uma configuração, e entradas e saídas. Observe que a codificação é feita com a configuração de “H.264 HD 720p VBR”. Usaremos o Microsoft Expression Encoder. Processadores de mídia adicionais estarão disponíveis à medida que parceiros do setor de mídia adicionais agregarem valor ao Media Services.
Parte 3 É onde o processamento real começa. Você pode pensar em um trabalho como sendo um fluxo de trabalho com um conjunto de tarefas. As tarefas podem ser encadeadas e podem ser executadas em paralelo.
Parte 4 Esse código é simplesmente o retorno de chamada que é executado automaticamente durante o processo de carregamento do vídeo. Normalmente, é usado para relatar a porcentagem de conclusão do processo de carregamento.

Gerenciando conteúdo

Um dos desafios associados ao gerenciamento de projetos com base em vídeo é controlar todos os ativos, trabalhos e tarefas. Produzir conteúdo frequentemente envolve dezenas de arquivos originais e, potencialmente, centenas mais criados como a saída codificada. Ser capaz de acompanhar e localizar um item específico para processamento adicional pode ser uma experiência assustadora. Automatizar esse processo com interfaces padrão é uma virada de jogo. A interface de gerenciamento do Media Services abrirá a porta para uma maior colaboração entre participantes, tornando possível coordenar fluxos de trabalho de longa duração de maneira muito mais eficiente. O objeto CloudMediaContext fornece uma interface intuitiva para localizar qualquer elemento associado ao fluxo de trabalho, organizado como uma série de coleções que podem ser consultadas usando bibliotecas comuns, como LINQ.

O código na Figura 5 demonstra a capacidade de fazer um loop pelos ativos e exibir as informações sobre arquivos de vídeo além de outros tipos de arquivo, como imagens. Observe que o objeto de contexto tem uma coleção de ativos e que um objeto de ativo tem uma coleção de objetos de arquivo.

Figura 5 Vários ativos associados em uma conta

static void Main(string[] args)
{
  // Part 1 - Connect to Media Services
  //          Loop through assets, displaying file information
  CloudMediaContext mediaContext = 
    new CloudMediaContext("[ ACCOUNT NAME ]",
    "[ ACCOUNT KEY ]");
  Console.WriteLine("ASSET INFORMATION");
  foreach (IAsset asset in mediaContext.Assets)
  {
    // Display the collection of assets.
    Console.WriteLine("Asset ID: " + asset.Id);
    Console.WriteLine("Name: " + asset.Name);
    // Display the files associated with each asset.
    foreach (IFileInfo fileItem in asset.Files)
    {
      Console.WriteLine("File Name: " + fileItem.Name);
      Console.WriteLine("File Create Date: " + fileItem.Created);
      Console.WriteLine("File Size: " + fileItem.ContentFileSize);
    }
  }
}

O código na Figura 6 ilustra a capacidade de executar consultas LINQ para pesquisar ativos específicos. Tendo em mente que milhares de arquivos estão sendo potencialmente gerenciados, uma funcionalidade de pesquisa como essa pode ser uma tremenda ajuda.

Figura 6 A impressionante simplicidade do LINQ ao pesquisar ativos usando um nome ou uma ID

// Returns an asset, given an asset name
static IAsset GetAssetNameFromContext(
  CloudMediaContext mediaContext, string assetName)
{
  IAsset asset = mediaContext.Assets.Where(a => a.Name ==
    assetName).FirstOrDefault();
  if (asset != null)
    return asset;
  else
    return null;
}
// Returns an asset, given an asset Id
static IAsset GetAssetIdFromContext(
  CloudMediaContext mediaContext, string assetId)
{
  IAsset asset = mediaContext.Assets.Where(a => a.Id ==
    assetId).FirstOrDefault();
  if (asset != null)
    return asset;
  else
    return null;
}

Políticas de acesso

Controlar quais usuários podem exibir e acessar ativos específicos é uma capacidade interna da estrutura do Media Services. Para controlar os direitos de segurança, os proprietários de conteúdo podem especificar de forma programática uma política de acesso, em que detalhes como permissões de leitura/gravação, além de quanto tempo o acesso estará disponível, são especificados. Esses são recursos poderosos no contexto de compartilhar fluxos de trabalho com outros participantes de vídeo.

Esta seção mostra como executar tarefas básicas com políticas de acesso, como criá-las e atribuí-las a um ativo, além de listar as já criadas. O objetivo do código na Figura 7 é configurar uma política de “leitura”, permitindo que o vídeo seja acessado por apenas 30 minutos. O código começa carregando winsat.wmv. Daí, uma nova política de acesso é criada, chamada de CanReadFor30Minutes, que significa que o arquivo pode ser lido apenas dentro de 30 minutos do processo de carregamento. A próxima etapa é vincular a política de acesso ao arquivo de vídeo carregado.

Figura 7 Expondo temporariamente um vídeo para download

static void Main(string[] args)
{
  // Part 1 - Specify an asset to upload
  //          Connect to Media Services
  string inputFilePath =
    @"C:\windows\Performance\WinSat\winsat.wmv";
  CloudMediaContext mediaContext =
    new CloudMediaContext("[ ACCOUNT NAME ]", "[ ACCOUNT KEY ]");
  // Part 2 - Upload an asset
  //          Create a policy for the asset
  //          Link access policy to asset
  IAsset asset = mediaContext.Assets.Create(inputFilePath);
  // Because this is a single-file asset, get the name of first file.
  string fileName = asset.Files[0].Name;
  IAccessPolicy readPolicy = mediaContext.AccessPolicies.Create(
    "CanReadFor30Minutes",
    TimeSpan.FromMinutes(30),
    AccessPermissions.Read);
  // Part 3 - Define a locator based on the read policy
  //          and expiration date
  //          Print the path for the locator you created
  //          Get the locator path Uri
  //          Build the full path to the file associated
  //          with the locator.
  ILocator locator = mediaContext.Locators.CreateSasLocator(
    asset, readPolicy);
  Console.WriteLine("Locator path: " + locator.Path);
  var uriBuilder = new UriBuilder(locator.Path);
  uriBuilder.Path += Path.AltDirectorySeparatorChar + fileName;
  Uri fullUrl = uriBuilder.Uri;
  // Part 4 - Print the full path to the file
  Console.WriteLine("Full URL to file: " + fullUrl);
}

Um localizador é uma cópia persistente do arquivo de política cuja localização é expressa como um URI. O localizador permite acessar o ativo nos termos especificados pela política. Nesse caso, para acessar o ativo (o vídeo carregado) dentro do limite de tempo de 30 minutos, precisamos usar a URL completa, junto com o arquivo do localizador. Veja fullUrl na Figura 7.

Baixando ativos processados

Finalmente, o objetivo do código na Figura 8 é baixar o conteúdo de vídeo no armazenamento local. Nesse caso, o arquivo winsat.mp4 é a saída codificada em H.264, gerado do vídeo original armazenado como winsat.wmv. Você pode chamar a função assim:

DownloadAsset("nb:cid:UUID:a0297fe4-7080-4393-b874-7ddf0f759c40", @"c:\temp");

Figura 8 Baixando ativos do Windows Azure Media Services

static void DownloadAsset(string assetId, 
    string outputMediaFilesFolder)
{
  // Part 1 - Connect to Media Services
  //          Get an existing asset based on assetId passed in.
  CloudMediaContext mediaContext =
    new CloudMediaContext("[ ACCOUNT NAME ]","[ ACCOUNT KEY ]");
  IAsset asset = mediaContext.Assets.Where(a => a.Id ==
    assetId).SingleOrDefault();
  // Part 2 - If the asset exists, download the first file in the asset
  //          Download to outputMediaFilesFolder      
  if (asset != null)
  {
    Console.WriteLine("Asset name: " + asset.Name);
    IFileInfo theFile = asset.Files.FirstOrDefault();
    // You could iterate through the asset.Files collection with a
    // foreach statement, and download all files for assets that
    // have multiple files.
    // Example: foreach(IFileInfo file in asset.Files)
    // Download the file to the specified local folder.
    if (theFile != null)
      theFile.DownloadToFile(Path.GetFullPath(outputMediaFilesFolder +
        Path.DirectorySeparatorChar + theFile.Name));
    else
      Console.WriteLine("No files available for this asset.");
  }
  else
  {
    Console.WriteLine("Asset not available.");
  }
}

O assetId de winsat.mp4 é nb:cid:UUID:a0297fe4-7080-4393-b874-7ddf0f759c40. É um simples caso de solicitar o recurso de download por seu assetId e especificar uma pasta de destino para o download.

Benefícios da computação em nuvem

Concluindo, os recursos do Media Services do Windows Azure simplificam o processo de codificação e distribuição de conteúdo de vídeo para diversos dispositivos ou canais da Web que exigem formatos e resoluções diferentes. Isso é obtido aproveitando os benefícios que a computação em nuvem oferece, incluindo escalabilidade de computação e armazenamento com base em demanda variável. Isso, junto com uma rica API baseada em REST e uma biblioteca cliente .NET, facilita o processo de criação, gerenciamento e manutenção de fluxos de trabalho que podem ser aperfeiçoados com componentes criados em um vasto ecossistema de parceiros.

O Media Services representa um grande salto à frente na produção, gerenciamento e entrega de conteúdo de vídeo, permitindo que você automatize e reúna uma grande variedade de ativos digitais e os organize em um local centralizado ou mesmo em locais distribuídos. Como o vídeo está pronto para um crescimento fenomenal na Web durante os próximos anos, o Media Services chega em uma hora perfeita.

Mais adiante abordaremos a API REST em detalhes, além do suporte de terceiros para codificadores personalizados e recursos avançados.

Bruno Terkaly é um desenvolvedor e divulgador da Microsoft. Seu conhecimento profundo é o resultado de anos de experiência no campo, escrevendo código com uma grande quantidade de plataformas, linguagens, estruturas, SDKs, bibliotecas e APIs. Ele escreve código, participa de blogs e fornece apresentações ao vivo sobre como criar aplicativos baseados em nuvem, especificamente usando a plataforma Windows Azure.

Ricardo Villalobos é um arquiteto de software experiente com mais de 15 anos de experiência em projeto e criação de aplicativos para empresas na indústria de gerenciamento da cadeia de suprimentos. Com diferentes certificações técnicas, bem como um MBA em gerenciamento de cadeia de suprimentos da Universidade de Dallas, ele trabalha como arquiteto divulgador do Windows Azure da Microsoft.

Agradecemos aos seguintes especialistas técnicos pela revisão deste artigo: John Deutscher, Samuel Ng e Tim Teebken