Este artigo foi traduzido por máquina.

IIS Smooth Streaming

Aprimorando as experiências de vídeo do Silverlight com dados contextuais

Jit Ghosh

Baixe o código de exemplo

Há dois requisitos principais para habilitar uma experiência de exibição livre de problema no fornecimento de vídeo digital com base na Web, de alta definição. Primeiro, o provedor de vídeo precisa para oferecer suporte a taxas de bits alta entrega vídeo pela rede. Segundo, o computador cliente precisa para oferecer suporte a disponibilidade contínua de capacidade para decodificar o vídeo em sua resolução mais completo de processamento.

No entanto, a realidade é que largura de banda da rede para computadores conectados pode flutuar muito ao longo do tempo e em determinadas partes do mundo de alta largura de banda tem um preço muito alto ou não está disponível para muitos consumidores. Com isso, a capacidade de processamento do computador cliente pode variar, dependendo da carga de CPU em qualquer dado momento. Como resultado, os consumidores são suscetíveis a degradação na qualidade de sua experiência de visualização quando um vídeo stutters ou congela enquanto aguarda o player para dados suficientes para mostrar a próxima definir quadros de vídeo ou aguardando ciclos da CPU para decodificar os quadros de buffer.

Adaptável de fluxo contínuo é uma abordagem de entrega de vídeo que resolve o problema de entrega de conteúdo suave e decodificação. Com streaming adaptável, conteúdo de vídeo é codificado em um intervalo de taxas de bits e disponibilizado por meio de um servidor de fluxo especializado. Um player de streaming adaptável constantemente monitora várias métricas de utilização de recursos no computador cliente e usa essas informações para calcular a taxa de bits apropriado que o cliente pode decodificar e exibir cada considerando as restrições do recurso atual com mais eficiência.

O player solicita partes do vídeo codificado a essa taxa de bit apropriado no momento e servidor de fluxo de responde com o conteúdo das fontes vídeo codificadas a essa taxa de bits. Como resultado, quando degradar condições de recursos, o player pode continuar a exibir o vídeo sem quaisquer interrupções significativas, com apenas uma ligeira degradação na resolução de geral, até que uma melhoria ou ainda mais a degradação em condições faz com que uma taxa de bits diferentes ao ser solicitado.

Esse tipo de uma colaboração contínua entre o player e o servidor requer uma implementação especial da lógica no servidor de fluxo contínuo e o tempo de execução dos clientes o player a implementação do processamento. Streaming suave do Internet Information Server (IIS) é a implementação de servidor de adaptável fluxo contínuo por HTTP da Microsoft. A implementação de cliente é fornecida como uma extensão para o Microsoft Silverlight.

IIS suave Streaming Player Development Kit é uma biblioteca do Silverlight que permite que aplicativos consumir conteúdo sendo transmitido por fluxo suave do IIS. Ele também fornece uma API avançada que oferece acesso programático aos vários aspectos da lógica do fluxo suave.

Neste artigo eu irá orientá-lo as noções básicas sobre fluxo suave e explique como você pode usar o IIS suave Streaming Player Development Kit para criar experiências avançadas em torno do vídeo. Especificamente, examinarei usando o Kit de desenvolvimento do Player para consumir um fluxo, com um exame de fechamento do modelo de dados do lado do cliente para fluxos e trilhas. Vou mostrar como consumir fluxos de dados adicionais, como legendas codificadas e animações e mesclar fluxos de dados externos com uma apresentação existente. Você verá como agendar clipes externos, como anúncios dentro de uma apresentação, lidar com as taxas de reprodução variável e criar manifestos compostos que prestam a cenários de edição robustos.

Works Streaming como suave

Você pode codificar o vídeo para suavizar streaming usando um dos perfis fornecidos no Expression Encoder 3.0. Um arquivo de vídeo de origem, vários arquivos são criados na pasta de destino. Figura 1 mostra os arquivos criados para um vídeo de origem chamado FighterPilot.wmv.


Figura 1 de arquivos gerados para suavizar Streaming pelo Expression Encoder

Cada um dos arquivos com uma extensão .ismv contém o vídeo codificado em uma taxa de bits específico. Por exemplo, o FighterPilot_331.ismv contém o vídeo codificado a uma taxa de bits de 331 kbps, enquanto FighterPilot_2056.ismv contém o vídeo codificado em 2 mbps.

Para cada taxa de bits, o conteúdo de vídeo é dividido em fragmentos de dois segundos e os arquivos .ismv armazenam esses fragmentos em um formato de arquivo chamado PIFF (formato de arquivo interoperáveis Protected). Observe que você pode fazer com que faixas de áudio adicionais (ou áudio apenas no caso da apresentação é áudio somente) codificados em arquivos semelhantes que têm uma extensão .isma.

Obtendo suave Streaming ambiente

Para testar os exemplos discutidos neste artigo, você precisará preparar um ambiente de streaming suave em suas máquinas de desenvolvimento.

Ingrediente do servidor é simples: Você precisará fazer o download e instalar o IIS Media Services 3.0 para IIS7 por de iis.net/media usando o instalador do Microsoft Web Platform.

Você precisará de uma cópia do Microsoft Expression Encoder 3.0 para preparar vídeos para streaming suave. Enquanto houver uma versão de avaliação gratuita do Expression Encoder 3.0, essa versão não inclui suporte para fluxo contínuo suave. Você precisará de uma instalação licenciada do Expression Encoder para criar seu próprio vídeo.

Para obter detalhes adicionais sobre a preparação do ambiente, visite learn.iis.net/page.aspx/558/smooth-streaming-for-iis-70---getting-started .

O arquivo FighterPilot.ism é um manifesto do servidor, que é estruturado em formato SMIL (Synchronized Multimedia Integration Language) e contém um mapeamento de níveis de qualidade e taxas de bits para os arquivos .ismv e .isma. Este mapeamento no manifesto do servidor é usado pelo servidor para acessar os arquivos do disco certo para criar o próximo fragmento do conteúdo codificado com taxa de bits direito, antes de responder a uma solicitação do lado do cliente. Figura 2 mostra um trecho de um arquivo de manifesto do servidor.

Figura 2 Sample Server manifesto

<smil xmlns="http://www.w3.org/2001/SMIL20/Language">
  <head>
    <meta name="clientManifestRelativePath"
      content="FighterPilot.ismc" />
  </head>
  <body>
    <switch>
      <video src="FighterPilot_2962.ismv"
        systemBitrate="2962000">
        <param name="trackID"
          value="2" valuetype="data" />
      </video>
      <video src="FighterPilot_2056.ismv"
        systemBitrate="2056000">
        <param name="trackID"
          value="2" valuetype="data" />
      </video>
      ...
      <audio src="FighterPilot_2962.ismv"
        systemBitrate="64000">
        <param name="trackID"
          value="1" valuetype="data" />
      </audio>
    </switch>
  </body>
</smil>

O manifesto do servidor também contém um mapeamento para um arquivo de manifesto de cliente (identificado pelo .ismc extensão), que meu exemplo, é FighterPilot.ismc. O manifesto do cliente contém todas as informações que o cliente Silverlight precisará acessar a várias mídias e fluxos de dados, bem como taxas de metadados sobre esses fluxos, como os níveis de qualidade, disponíveis de bits, informações, dados de inicialização do codec de intervalos e assim por diante. A lógica do cliente usará esses metadados para amostra e decodificar os fragmentos e switches de taxa de bits com base em condições locais predominante de solicitação.

Em tempo de execução, a apresentação começa com o cliente solicitar o manifesto do cliente ao servidor. Quando o cliente recebe o manifesto, verifica para ver quais taxas de bits estão disponíveis e solicitações de fragmentos de conteúdo começando a menor taxa de bits disponível. Em resposta, o servidor prepara e envia os fragmentos lendo os dados do arquivo de disco codificado a essa taxa de bits (usando o mapeamento no manifesto do servidor). O conteúdo é exibido no cliente.

O cliente solicita gradualmente maiores taxas de bits conforme permitido pela lógica de monitoração de recursos e eventualmente atinge a taxa de bits permitido maior conforme determinado pelas condições predominante do recurso. Esse intercâmbio continua até que a lógica de monitoramento do cliente detecta uma alteração nas condições de recursos, resultando em uma taxa de bits desejado inferior diferentes. Solicitações de clientes subseqüentes são para codificado pela taxa de bits nova mídia e o servidor novamente responde adequadamente. Isso continua até que a apresentação completa ou for interrompida.

Streaming suave com o Silverlight

Obtenção de vídeo para reproduzir no Silverlight é um esforço bastante simples. Em um nível fundamental, tudo o que você realmente precisa fazer é adicionar uma instância do tipo MediaElement ao arquivo XAML, defina as propriedades adequadas para controlar o comportamento de MediaElement e certifique-se de que a propriedade MediaElement.Source aponta para uma fonte de mídia válidos URI. Por exemplo, esse XAML será executar o vídeo FighterPilot.wmv automaticamente assim que a página do Silverlight é iniciada em um retângulo de 640 x 360:

<MediaElement AutoPlay="True" 
  Source="http://localhost/Media/FighterPilot.wmv" 
  Width="640" Height="360" />

O tipo System.Windows.Controls.MediaElement também expõe uma API que permite controlar o comportamento da experiência de reprodução no código e para construir um player completo com controles padrão, como reproduzir, pausar, busca e assim por diante. Isso funciona abordagem ótima com um progressivamente baixado ou HTTP transmitido mídia, desde que seja que o runtime do Silverlight possui suporte interno para o formato de contêiner e a codificação usada.

E sobre formatos de arquivo ou codecs que não são suportados prontos para uso pelo Silverlight? O tipo MediaStreamSource (MSS) permite que um mecanismo de extensibilidade que permite que você assuma o controle de arquivo de mídia, análise e o processo de decodificação apresentando suas próprias analisador personalizado e o decodificador ao pipeline de mídia do Silverlight. Para fazer isso, você precisa implementar um tipo concreto estendendo System.Windows.Media.MediaStreamSource abstrata e em seguida passar uma instância dela para o uso do método MediaElement.SetSource MediaElement.

A implementação de MSS precisará lidar com todos os aspectos do processo de consumo de mídia de processamento real — receba o fluxo de mídia de um local remoto, para analisar o contêiner e metadados associados, a amostragem de áudio individual e Exemplosos de vídeo e passá-los para MediaElement para processamento.

Porque a lógica necessária para decodificar o fluxo suave não foi incorporada ao Silverlight, a versão primeira do Streaming suave (parte do IIS Media Services 2.0) era acompanhada por uma implementação personalizada do MSS que tratados todos comunicação, análise e lógica de amostragem e também implementaram a máquina e funcionalidade de monitoramento de estado de rede.

Em sua maioria, essa abordagem funcionava bem para streaming suave, mas houve alguns problemas. O MSS é essencialmente uma caixa preta é a única API expõe diretamente facilitar a troca de bruto de áudio e vídeo exemplos entre si e um MediaElement. Como um desenvolvedor do Silverlight, você não tem uma maneira direta de interface com o MSS enquanto em ação. Se o conteúdo que está sendo consumido tivesse dados adicionais, como texto incorporado, animação ou ângulos de câmera secundário, ou se as taxas de reprodução variável, como a solução de fluxo permitida para o controle mais refinado sobre os fluxos, não era possível para você por meio de programação de acesso que dados adicionais de maneira estruturada porque eram limitados a interface com a API fixa definido que MediaElement sempre expõe.

Para suavizar streaming, isso representa um desafio. Como você verá neste artigo, streaming suave manifestos e formatos de arquivo/fios são bastante ricos em termos de conteúdo adicional e metadados que podem ser transportados e com a abordagem de MSS você não foi possível obter essa informação. Você precisa de uma API do Silverlight que oferece mais controle sobre e acessar a solução de fluxo contínuo suave.

IIS suavizar Streaming Player Development Kit

E que me leva ao IIS suave Streaming Player Development Kit. O Player Development Kit consiste em um único assembly denominado 
Microsoft.Web.Media.SmoothStreaming.dll. Em seu núcleo, é um tipo nomeado Microsoft.Web.Media.SmoothStreaming.SmoothStreamingMediaElement (SSME). Usando SSME no seu código é quase idêntico ao modo como você usaria um MediaElement regular:

<UserControl x:Class="SSPlayer.Page"
  xmlns="https://schemas.microsoft.com/winfx/2006/xaml/presentation" 
  xmlns:x="https://schemas.microsoft.com/winfx/2006/xaml" 
  xmlns:ss="clr-namespace:Microsoft.Web.Media.SmoothStreaming;assembly=Microsoft.Web.Media.SmoothStreaming">
  <Grid x:Name="LayoutRoot" Background="White">
    <ss:SmoothStreamingMediaElement AutoPlay="True" 
      Width="640" Height="360"
      SmoothStreamingSource="http://localhost/SmoothStreaming/Media/FighterPilot/FighterPilot.ism/manifest"/>
  </Grid>
</UserControl>

A propriedade SmoothStreamingSource aponta SSME para uma apresentação do Streaming suave válida. Em geral, a API SSME é um superconjunto da API do MediaElement; esta propriedade é uma das poucas diferenças. SSME expõe a propriedade Source como MediaElement faz, mas SSME também expõe a propriedade SmoothStreamingSource anexar fluxos suaves. Se você estiver criando players que precisam ser capazes de consumir fluxos suaves e outros formatos de MediaElement tradicionalmente com suporte, você pode usar com segurança SSME, mas você provavelmente precisará criar um código para definir a propriedade certa para anexar a fonte de mídia. Algo parecido com:

private void SetMediaSource(string MediaSourceUri, 
  SmoothStreamingMediaElement ssme) {

  if (MediaSourceUri.Contains(".ism"))
    ssme.SmoothStreamingSource = new Uri(MediaSourceUri); 
  else
    ssme.Source = new Uri(MediaSourceUri); 
}

A outra diferença importante ter em mente é que SSME não expõe uma SetSource sobrecarga que aceita um tipo MediaStreamSource. Se você precisar usar um MSS personalizado, você deverá fazer isso por meio de MediaElement.

Faixas e fluxos

O manifesto do cliente Streaming suave contém rich metadados sobre a apresentação e pode ser útil ter acesso através de programação para esses metadados em seu aplicativo de player. SSME expõe partes dos metadados por meio de uma API bem definida em uma organização de fluxos e trilhas em cada fluxo.

Os metadados geral para trilhas de um tipo específico de representa um fluxo, vídeo, áudio, texto, anúncios e assim por diante. O fluxo também atua como um contêiner para várias faixas do mesmo tipo subjacente. No manifesto cliente (consulte do Figura 3), cada entrada StreamIndex representa um fluxo. Pode haver vários fluxos na apresentação, conforme representado por várias entradas StreamIndex. Também pode haver vários fluxos do mesmo tipo. Em tais casos, o nome de fluxo pode ser usado para disambiguate entre várias ocorrências do mesmo tipo.

Figura 3 do trecho de um manifesto do cliente

<SmoothStreamingMedia MajorVersion="2" MinorVersion="0" 
  Duration="1456860000">
  <StreamIndex Type="video" Chunks="73" QualityLevels="8" 
    MaxWidth="1280" MaxHeight="720" 
    DisplayWidth="1280" DisplayHeight="720"
    Url="QualityLevels({bitrate})/Fragments(video={start time})">
    <QualityLevel Index="0" Bitrate="2962000" FourCC="WVC1" 
      MaxWidth="1280" MaxHeight="720"
      CodecPrivateData="250000010FD37E27F1678A27F859E80490825A645A64400000010E5A67F840" />
    <QualityLevel Index="1" Bitrate="2056000" FourCC="WVC1" 
      MaxWidth="992" MaxHeight="560" 
      CodecPrivateData="250000010FD37E1EF1178A1EF845E8049081BEBE7D7CC00000010E5A67F840" />
    ...
    <c n="0" d="20020000" />
    <c n="1" d="20020000" />
    ...
    <c n="71" d="20020000" />
    <c n="72" d="15010001" />
  </StreamIndex>
  <StreamIndex Type="audio" Index="0" FourCC="WMAP" 
    Chunks="73" QualityLevels="1" 
    Url="QualityLevels({bitrate})/Fragments(audio={start time})">
    <QualityLevel Bitrate="64000" SamplingRate="44100" Channels="2" 
      BitsPerSample="16" PacketSize="2973" AudioTag="354" 
      CodecPrivateData="1000030000000000000000000000E00042C0" />
    <c n="0" d="21246187" />
    <c n="1" d="19620819" />
    ...
    <c n="71" d="19504762" />
    <c n="72" d="14900906" />
  </StreamIndex>
  <StreamIndex Type="text" Name="ClosedCaptions" Subtype="CAPT" 
    TimeScale="10000000" ParentStreamIndex="video" 
    ManifestOutput="TRUE" QualityLevels="1" Chunks="2" 
    Url="QualityLevels({bitrate},{CustomAttributes})/Fragments(ClosedCaptions={start time})">
    <QualityLevel Index="0" Bitrate="1000" 
      CodecPrivateData="" FourCC=""/> 
    <c n="0" t="100000000">
      <f>...</f> 
    </c>
    <c n="1" t="150000000">
      <f>...</f>
    </c>
  </StreamIndex>
  ...
</SmoothStreamingMedia>

O tipo de StreamInfo representa o fluxo do código do Silverlight. Uma vez SSME baixa o manifesto do cliente, ele dispara o evento SmoothStreamingMediaElement.ManifestReady. Agora a propriedade de coleção SmoothStreamingMediaElement.AvailableStreams contém uma instância StreamInfo para cada entrada StreamIndex no manifesto do cliente.

Para um determinado fluxo de vídeo no manifesto do cliente, a faixa de vídeo é dividida em vários fragmentos da duração de dois segundos, e cada elemento no manifesto do c representa metadados para o fragmento. Nesse caso, os fragmentos na faixa são contíguos e definem durante todo o período da faixa de vídeo sem as quebras de página entre — em outras palavras, o fluxo não é esparso.

Para um fluxo de closed caption, a faixa inclui apenas dois fragmentos, cada um com informações de temporização individuais (o atributo t no elemento c). Além disso, o atributo ParentStreamIndex é definido como “ vídeo ”, pelo fluxo de legenda codificada com o fluxo de vídeo. Isso faz com que o fluxo de legenda codificada para alinhar as informações de tempo do fluxo de vídeo — o fluxo de closed caption começa e termina exatamente com o seu fluxo de vídeo pai, e a primeiro legenda é exibida 10 segundos no fluxo de vídeo enquanto o 
second é exibida a 15 segundos de vídeo. Um fluxo no qual a linha do tempo é baseada em um fluxo de pai e os fragmentos são não-contíguos é chamado de um fluxo esparso.

Uma trilha é uma seqüência com tempo de fragmentos de conteúdo de um tipo específico — texto, áudio ou vídeo. Cada trilha é representada usando uma instância de um tipo TrackInfo e todas as faixas em um fluxo são disponibilizadas através da propriedade de coleção StreamInfo.AvailableTracks.

Cada faixa no manifesto cliente é identificada exclusivamente por meio de um QualityLevel. Um QualityLevel é identificada pela taxa de bit associados e é exposto por meio da propriedade TrackInfo.bitrate. Por exemplo, um fluxo de vídeo no manifesto cliente pode ter vários QualityLevels, cada um com uma taxa de bits exclusivo. Cada representa um controle exclusivo do conteúdo, mesmo vídeo codificado na taxa de bits especificada pelo QualityLevel.

Manifesto de saída e atributos personalizados

Atributos personalizados são uma maneira de adicionar informações específicas faixa ou fluxo adicional para o manifesto. Atributos personalizados são especificados usando um elemento de CustomAttribute, que pode conter vários elementos de dados, expressos como pares chave/valor. Cada elemento de dados é expressa como um elemento de atributo, com atributos de chave e valor especificando a chave de elemento de dados e o valor do elemento de dados. Em casos onde níveis distintos de qualidade não se aplicam, como várias faixas em um fluxo com o mesmo nome de faixa e taxa de bits, um atributo personalizado também podem ser usadas para disambiguate faixas uns dos outros. Figura 4 mostra um exemplo de uso do atributo personalizado.

Figura 4 de usando atributos personalizados na guia Manifestar de cliente

<StreamIndex Type="video" Chunks="12" QualityLevels="2" 
  MaxWidth="1280" MaxHeight="720" 
  DisplayWidth="1280" DisplayHeight="720" 
  Url="QualityLevels({bitrate})/Fragments(video={start time})">
  <CustomAttributes>
    <Attribute Key="CameraAngle" Value="RoofCam"/>
    <Attribute Key="AccessLevel" Value="PaidSubscription"/>
  </CustomAttributes>
  <QualityLevel Index="0" Bitrate="2962000" FourCC="WVC1" 
    MaxWidth="1280" MaxHeight="720"
    CodecPrivateData="250000010FD37E27F1678A27F859E80490825A645A64400000010E5A67F840">
    <CustomAttributes>
      <Attribute Name = "hardwareProfile" Value = "10000" />
    </CustomAttributes>
  </QualityLevel>
...
</StreamIndex>

Atributos personalizados adicionados a um manifesto não afetam nenhum comportamento SSME automaticamente. Eles são uma maneira para o fluxo de trabalho de produção apresentar dados personalizados no manifesto que seu código do player pode receber e agir. Por exemplo, do Figura 4, convém procurar a chave de atributo personalizado AccessLevel na coleção de atributos personalizados de fluxo de vídeo e expor esse fluxo de vídeo somente para pagar os assinantes conforme instruído no valor do atributo.

A propriedade de coleção StreamInfo.CustomAttributes expõe um dicionário de pares chave/valor de seqüência de caracteres para todos os atributos personalizados aplicados no nível do fluxo (como elementos de filhos de CustomAttribute diretos ao elemento StreamIndex). A propriedade TrackInfo.CustomAttributes expõe a mesma para todos os atributos personalizados aplicados no nível de controle (como filhos diretos do elemento QualityLevel).

Quando o atributo ManifestOutput no fluxo (o elemento StreamIndex) é definido como TRUE, o manifesto do cliente, na verdade, pode conter os dados que representam cada fragmento para as faixas no fluxo. A Figura 5 mostra um exemplo.

Figura 5 de manifesto de saída

<StreamIndex Type="text" Name="ClosedCaptions" Subtype="CAPT" 
  TimeScale="10000000" ParentStreamIndex="video" 
  ManifestOutput="TRUE" QualityLevels="1" Chunks="6" 
  Url="QualityLevels({bitrate},{CustomAttributes})/Fragments(ClosedCaptions={start time})"> 
  <QualityLevel Index="0" Bitrate="1000" CodecPrivateData="" FourCC=""/> 
  <c n="0" t="100000000">
    <f>PENhcHRpb24gSWQ9IntERTkwRkFDRC1CQzAxLTQzZjItQTRFQy02QTAxQTQ5QkFGQkJ9IiAKICAgICAgICBBY3Rp</f>
  </c>
  <c n="1" t="150000000">
    <f>PENhcHRpb24gSWQ9IntERTkwRkFDRC1CQzAxLTQzZjItQTRFQy02QTAxQTQ5QkFGQkJ9IiAKICAgI</f>
  </c>
...
</StreamIndex>

Observe o conteúdo aninhado dentro de elementos f — cada representa dados de item de legenda a ser exibido na hora especificada por bloco contendo. A especificação de manifesto do cliente requer que os dados ser representado como uma seqüência de caracteres codificada na base64 versão do item de dados original.

A propriedade de coleção TrackInfo.TrackData contém uma lista de instâncias TimelineEvent — um para cada elemento f corresponde da faixa. Para cada entrada de TimelineEvent TimelineEvent.EventTime representa o ponto de tempo na seqüência e o TimelineEvent.EventData fornece a seqüência de caracteres de texto codificado na base64. TrackInfo também oferece suporte a taxa de bits, CustomAttributes, índice, nome e ParentStream propriedades.

Selecionar faixas e fluxos

Há muitas maneiras interessantes, você pode usar a fluxos e faixas de metadados e API em código do aplicativo.

Pode ser útil ter a capacidade de selecionar faixas específicas dentro de um fluxo e filtrar o resto. Um cenário comum é uma experiência de visualização Graduada com base no nível do assinante de acesso, em um nível básico ou livre que servem a versão de baixa resolução do conteúdo e expor a versão de alta definição somente para assinantes do nível premium:

if (subscriber.AccessLevel != "Premium") {
  StreamInfo videoStream = 
    ssme.GetStreamInfoForStreamType("video");
  List<TrackInfo> allowedTracks = 
    videoStream.AvailableTracks.Where((ti) => 
    ti.Bitrate < 1000000).ToList();
  ssme.SelectTracksForStream(
    videoStream, allowedTracks, false);
}

GetStreamInfoForStreamType aceita um tipo de fluxo literal e retorna a instância StreamInfo correspondente. Uma consulta LINQ no StreamInfo.AvailableTracks recupera uma lista de controles que oferecem uma taxa de bits de menos de 1 mbps — em outras palavras, um vídeo de definição padrão para os assinantes que não sejam premium. O método SelectTracksForStream, em seguida, pode ser usado para filtrar a lista de trilhas em desse fluxo apenas de controles que você deseja expor.

O último parâmetro SelectTracksForStream, quando definido como true, indica ao SSME que quaisquer dados armazenados nos buffers de look-ahead devem ser limpo imediatamente. Para obter a lista atual selecionada de faixas a qualquer momento, você pode usar a propriedade StreamInfo.SelectedTracks, enquanto a propriedade StreamInfo.AvailableTracks continua a expor todas as faixas disponíveis.

Lembre-se de que Streaming suave permite que vários fluxos do mesmo tipo coexistam no manifesto do cliente. Na beta atual do IIS suave Streaming Player Development Kit, o método de GetStreamInfoForStreamType retorna a primeira ocorrência de um fluxo do tipo especificado caso haja vários fluxos desse tipo, que pode não ser que você desejar. No entanto, não há nada parar de ignorar esse método e, em vez disso, usar uma consulta na coleção AvailableStreams diretamente para obter o direito de StreamInfo. O trecho a seguir mostra uma consulta LINQ que obtém um fluxo de texto chamado “ ticker ”:

StreamInfo tickerStream = 
  ssme.AvailableStreams.Where((stm) => 
  stm.Type == "text" && 
  stm.Name == "ticker").FirstOrDefault();

Usando fluxos de texto

Uma apresentação de áudio/vídeo pode ser necessário exibir o conteúdo adicional que atingiu o tempo junto a seqüência de vídeo primária em pontos de tempo específico. Exemplos poderiam ser legendas codificadas, anúncios, alertas de notícias, animações de sobreposição e assim por diante. Um fluxo de texto é um local conveniente para expor esse tipo de conteúdo.

Uma abordagem para incluir um fluxo de texto em sua apresentação seria mux em controles de texto juntamente com os controles de vídeo durante a codificação vídeo, para que os fragmentos de conteúdo para o controle de texto são entregues a partir do servidor, atingiu o tempo apropriadamente com o vídeo.

Outra opção é utilizar o recurso de manifesto de saída discutido anteriormente para criar o conteúdo de texto no manifesto cliente propriamente dito. Let’s dê uma olhada mais detalhada essa segunda abordagem.

Para começar, você precisa preparar um manifesto do cliente com os fluxos de texto. Em um fluxo de trabalho de mídia de produção, pode haver muitas maneiras diferentes de injetar o conteúdo no manifesto durante ou após a codificação e os dados podem estar vindo de várias fontes diferentes, como plataformas de servidores de anúncio e geradores de legenda. Mas, neste exemplo, vou usar um arquivo de dados XML simples como a fonte de dados, usar algumas LINQ sobre consultas XML para fabricar os fluxos de texto e inseri-los em um manifesto de cliente existente.

A estrutura dos dados não precisa ser complexa. (Você encontrará o arquivo completo no download do código deste artigo. Vou mostrar trechos para fins ilustrativos.) O arquivo de dados começa com um elemento de trilhas e, em seguida, contém dois elementos ContentTrack. Cada entrada ContentTrack, por fim, resultará em um fluxo de texto distintas no manifesto do cliente. É o primeiro elemento ContentTrack para as legendas:

<ContentTrack Name="ClosedCaptions" Subtype="CAPT">

A segunda é para animações:

<ContentTrack Name="Animations" Subtype="DATA">

Cada ContentTrack contém vários elementos de eventos, com os atributos de tempo especificando os pontos de tempo no cronograma do vídeo quando esses eventos de texto precisam ocorrer. Os elementos de eventos, por sua vez, contêm os eventos de legenda real definidos em XML ou o XAML para animação como seções CDATA:

<Event time="00:00:10"> 
  <![CDATA[<Caption Id="{DE90FACD-BC01-43f2-A4EC-6A01A49BAFBB}" 
    Action="ADD">
    Test Caption 1
  </Caption>] ]> 
</Event>
<Event time="00:00:15"> 
  <![CDATA[<Caption Id="{DE90FACD-BC01-43f2-A4EC-6A01A49BAFBB}" 
    Action="REMOVE"/>] ]> 
</Event>

Observe que para cada evento closed caption adicionado, há um evento correspondente indica o ponto de tempo quando a legenda adicionada anteriormente precisa ser removido. O elemento caption contido na seção CDATA para um evento closed caption define um atributo action com um valor de adicionar ou remover para indicar a ação apropriada.

Meu LINQ sobre código XML transforma os dados XML em entradas apropriadas para um manifesto do cliente e os insere em um arquivo de manifesto de cliente existente. Você pode encontrar um exemplo no download de código para este artigo, mas Observação que o formato de dados demonstrado não faz parte o Kit de desenvolvimento de Player Streaming suave ou a especificação de fluxo suave e nenhuma é orientação prescritiva de alguma forma. Você pode definir qualquer estrutura de dados às necessidades do seu aplicativo, desde que você pode transformá-lo no formato apropriado exigido pela Streaming suave cliente manifesto especificação, que inclui o conteúdo do texto nas seções CDATA para um formato base64 de codificação.

Depois que a transformação é executada, o arquivo de manifesto resultante do cliente irá conter os fluxos de texto conforme mostrado no do Figura 6.

Figura 6 de cliente Manifest Excerpt com fluxos de conteúdo de texto

<SmoothStreamingMedia MajorVersion="2" MinorVersion="0" 
  Duration="1456860000">
  <StreamIndex Type="video" Chunks="73" QualityLevels="8" 
    MaxWidth="1280" MaxHeight="720" 
    DisplayWidth="1280" DisplayHeight="720"
    Url="QualityLevels({bitrate})/Fragments(video={start time})">
    <QualityLevel Index="0" Bitrate="2962000" FourCC="WVC1" 
      MaxWidth="1280" MaxHeight="720"
      CodecPrivateData="250000010FD37E27F1678A27F859E80490825A645A64400000010E5A67F840" />
    <QualityLevel Index="1" Bitrate="2056000" FourCC="WVC1" 
      MaxWidth="992" MaxHeight="560" 
      CodecPrivateData="250000010FD37E1EF1178A1EF845E8049081BEBE7D7CC00000010E5A67F840" />
    ...
    <c n="0" d="20020000" />
    <c n="1" d="20020000" />
    ...
    <c n="71" d="20020000" />
    <c n="72" d="15010001" />
  </StreamIndex>
  <StreamIndex Type="audio" Index="0" FourCC="WMAP" 
    Chunks="73" QualityLevels="1" 
    Url="QualityLevels({bitrate})/Fragments(audio={start time})">
    <QualityLevel Bitrate="64000" SamplingRate="44100" Channels="2" 
      BitsPerSample="16" PacketSize="2973" AudioTag="354" 
      CodecPrivateData="1000030000000000000000000000E00042C0" />
    <c n="0" d="21246187" />
    <c n="1" d="19620819" />
    ...
    <c n="71" d="19504762" />
    <c n="72" d="14900906" />
  </StreamIndex>
  <StreamIndex Type="text" Name="ClosedCaptions" Subtype="CAPT" 
    TimeScale="10000000" ParentStreamIndex="video" 
    ManifestOutput="TRUE" QualityLevels="1" Chunks="2" 
    Url="QualityLevels({bitrate},{CustomAttributes})/Fragments(ClosedCaptions={start time})">
    <QualityLevel Index="0" Bitrate="1000" 
      CodecPrivateData="" FourCC=""/> 
    <c n="0" t="100000000">
      <f>...</f> 
    </c>
    <c n="1" t="150000000">
      <f>...</f>
    </c>
  </StreamIndex>
  ...
</SmoothStreamingMedia>

Os fluxos de áudio e vídeo já existiam no manifesto do cliente do Figura 6 mostrado e adicionei os fluxos de texto de dois, chamados ClosedCaptions e animações, respectivamente. Observe que cada fluxo usa o fluxo de vídeo pai e define ManifestOutput como true. O primeiro é porque os fluxos de texto estão dispersos por natureza e parenting-los no fluxo de vídeo garante tempo correto de cada entrada conteúdo de texto (elementos c) ao longo da linha do tempo do fluxo de vídeo. O segundo é para garantir que o SSME lê os dados reais (os codificado na base64 seqüências dentro de elementos f) do próprio manifesto.

TimelineEvent e TimelineMarker

Agora examine let’s tomada de uso do conteúdo de SSME texto adicional. SSME expõe os fluxos de texto adicionais como instâncias de StreamInfo na propriedade AvailableStreams, com cada StreamInfo contendo os dados do controle como uma instância TrackInfo. A propriedade de coleção TrackInfo.TrackData contém muitas instâncias do tipo TimelineEvent quantos forem os eventos de texto em cada controle de texto. A propriedade TimelineEvent.EventData expõe uma matriz de bytes que representa o conteúdo do seqüência de caracteres (decodificado do seu formato codificado na base64), enquanto TimelineEvent.EventTime propriedade expõe o ponto de tempo em que este evento precisa ocorrer.

Ao iniciar reprodução da apresentação, como esses eventos são atingidos, SSME dispara o evento TimelineEventReached. Figura 7 mostra um exemplo de tratamento de closed caption e faixas de animação que foram adicionadas para o manifesto do cliente em do Figura 6.

Figura 7 Manipulando o evento TimelineEventReached

ssme.TimelineEventReached += 
  new EventHandler<TimelineEventArgs>((s, e) => { 
  //if closed caption event
  if (e.Track.ParentStream.Name == "ClosedCaptions" && 
    e.Track.ParentStream.Subtype == "CAPT") {

    //base64 decode the content and load the XML fragment
    XElement xElem = XElement.Parse(
      Encoding.UTF8.GetString(e.Event.EventData,
      0, e.Event.EventData.Length));

    //if we are adding a caption
    if (xElem.Attribute("Action") != null && 
      xElem.Attribute("Action").Value == "ADD") {

      //remove the text block if it exists
      UIElement captionTextBlock = MediaElementContainer.Children.
      Where((uie) => uie is FrameworkElement && 
        (uie as FrameworkElement).Name == (xElem.Attribute("Id").Value)).
        FirstOrDefault() as UIElement;
        if(captionTextBlock != null)
          MediaElementContainer.Children.Remove(captionTextBlock);

      //add a TextBlock 
      MediaElementContainer.Children.Add(new TextBlock() {
        Name = xElem.Attribute("Id").Value,
        Text = xElem.Value,
        HorizontalAlignment = HorizontalAlignment.Center,
        VerticalAlignment = VerticalAlignment.Bottom,
        Margin = new Thickness(0, 0, 0, 20),
        Foreground = new SolidColorBrush(Colors.White),
        FontSize = 22
      });
    }
    //if we are removing a caption
    else if (xElem.Attribute("Action") != null && 
      xElem.Attribute("Action").Value == "REMOVE") {

      //remove the TextBlock
      MediaElementContainer.Children.Remove(
        MediaElementContainer.Children.Where(
        (uie) => uie is FrameworkElement && 
        (uie as FrameworkElement).Name == 
        (xElem.Attribute("Id").Value)).FirstOrDefault() 
        as UIElement);
    }
  }

  //Logic for animation event
  ...
});

Como cada TimelineEvent é manipulado, ou inserir um TextBlock na interface do usuário para exibir uma legenda ou carregar a cadeia de caracteres XAML da animação e iniciar a animação (consulte o código para download para obter detalhes sobre a lógica de manipulação de animação).

Observe que, como o conteúdo de texto é codificado em base 64, é decodificado ao seu estado original. Observe também que o código verifica o atributo action no elemento caption para decidir se estiver adicionando uma legenda para a interface do usuário ou remover uma legenda existente. Para eventos de animação, você pode contar com um manipulador de conclusão da animação para removê-lo da interface do usuário.

Figura 8 mostra uma captura de tela de uma legenda que está sendo exibida e uma elipse ser animada sobrepostos em um vídeo em execução. Embora essa abordagem funciona bem, há um problema que você precisa considerar antes de usar essa técnica. A versão atual do SSME manipula TimlineEvents nos limites de dois segundos. Para entender isso melhor, let’s digamos que você tinha uma legenda fechada atingiu o tempo no ponto de 15,5 segundo tempo ao longo da linha do tempo de vídeo. SSME aumentaria o evento TimelineEventReached para este closed caption no mais próximo anterior tempo ponto em que é um múltiplo de 2 — em outras palavras, em aproximadamente 14 segundos.


Figura 8 fluxos de conteúdo de sobreposição de conteúdo usando texto e TimelineEvents

Se sua situação exige maior precisão e você não pode posicionar suas blocos de conteúdo próximos aos limites de dois segundos, a usando o TimelineEventReached para tratar de controles de conteúdo pode não ser a maneira correta. Você pode, no entanto, usar a classe TimelineMarker (como usado no tipo de MediaElement padrão) para adicionar marcadores ao cronograma que pode disparar o evento MarkerReached em qualquer granularidade que talvez seja necessário. O download do código deste artigo inclui o contorno de um método AddAndHandleMarkers que adiciona TimelineMarkers para cada evento de conteúdo e responde a eles no manipulador de eventos MarkerReached.

Mesclar External manifestos

Anteriormente você viu um exemplo de como adicionar fluxos adicionais de conteúdo para um manifesto do cliente. Essa abordagem funcionará bem se você tem acesso ao manifesto do cliente, mas você pode encontrar situações em que o acesso direto ao manifesto do cliente para tornar as inclusões necessárias não é possível. Você também pode encontrar situações em que os fluxos de conteúdo adicionais são condicionalmente dependentes de outros fatores (por exemplo, legendas codificadas em idiomas diferentes para diferentes locais). A inclusão dos dados para todas as condições possíveis o manifesto do cliente faz com que SSME gastar mais tempo de análise e carregando o manifesto.

SSME resolve esse problema, permitindo que você mesclar arquivos de manifesto externos em tempo de execução o manifesto do cliente original, que permite colocar em fluxos de dados adicionais e agir sobre os dados conforme mostrado anteriormente, sem ter que modificar o manifesto do cliente original.

Eis um exemplo de mesclagem do manifesto:

ssme.ManifestMerge += new 
  SmoothStreamingMediaElement.ManifestMergeHandler((sender) => {
  object ParsedExternalManifest = null;
  //URI of the right external manifest based on current locale
  //for example expands to 
  string UriString = 
    string.Format(
    "http://localhost/SmoothStreaming/Media/FighterPilot/{0}/CC.xml", 
    CultureInfo.CurrentCulture.Name);
  //parse the external manifest - timeout in 3 secs
  ssme.ParseExternalManifest(new Uri(UriString), 3000, 
    out ParsedExternalManifest);
  //merge the external manifest
  ssme.MergeExternalManifest(ParsedExternalManifest); 
});

Neste trecho de código a localidade predominante de anotações e usa um apropriado manifesto arquivo externo (chamado CC.xml armazenados em uma pasta nomeada para o identificador de idioma para a localidade) que contenha legendas codificadas no idioma correto para essa localidade. O método ParseExternalManifest aceita um URI apontando para o local do manifesto externo e retorna o manifesto analisado como um objeto com o terceiro parâmetro out para o método. O segundo parâmetro para o método aceita um valor de tempo limite, permitindo que você evitar o bloqueio de muito tempo na chamada de rede.

O método MergeExternalManifest aceita o objeto manifesto analisado retornado da chamada anterior e faz a mesclagem reais. Depois disso, fluxos e faixas de qualquer mesclada manifesto externo são disponibilizadas qualquer outra coisa no seu código player como instâncias StreamInfo e TrackInfo e podem ser tratadas como mostrado anteriormente.

É importante observar que as chamadas para ParseExternalManifest e MergeExternalManifest só podem ser feitas no manipulador de eventos ManifestMerge. Todas as chamadas para esses métodos fora do escopo do manipulador de eventos disparam um InvalidOperationException.

Tenha em mente que manifestos externos precisam ter uma extensão que tem um tipo de MIME associado registrado com o servidor Web do qual eles estão disponíveis. O uso de uma extensão comuns, como o XML é uma boa idéia porque o conteúdo é XML é assim mesmo. Se os arquivos de manifesto externos são fornecidos no mesmo servidor Web que está atuando como seu servidor de streaming suave, você deve se abstenha de usar a extensão .ismc porque o manipulador de IIS Media Services impede que arquivos .ismc sendo acessado diretamente e ParseExternalManifest falhará baixar o manifesto externo.

Contanto que a estrutura de um manifesto externo fica, ele precisa ser idêntico a um manifesto do cliente regular: elemento SmoothStreamingMedia nível superior, com elementos-filho StreamIndex apropriados para representar seus dados.

Agendamento do clipe

Você pode enfrentar a necessidade de inserir clipes de vídeo adicional em uma apresentação em pontos de tempo específico. Vídeos de anúncio, quebrando clipes de notícias ou preenchimento de uma apresentação são apenas alguns exemplos. O problema pode ser exibido em duas partes. Primeiro, os dados de conteúdo necessários a aquisição e determinar onde na linha de tempo para inseri-lo. Segundo, na verdade, agendamento e reproduzir os clipes. SSME incorpora a funcionalidade que torna essas tarefas relativamente simples de implementar.

Você pode continuar a usar a abordagem de um fluxo de texto inserido no manifesto do cliente, conforme ilustrado na seção anterior, para disponibilizar os dados de clipe ao seu código. Esta é uma fonte de dados de exemplo usada para informações de agendamento clipe:

<ContentTrack Name="AdClips" Subtype="DATA">
  <Event time="00:00:04">
    <![CDATA[<Clip Id="{89F92331-8501-41ac-B78A-F83F6DD4CB40}" 
    Uri="http://localhost/SmoothStreaming/Media/Robotica/Robotica_1080.ism/manifest" 
    ClickThruUri="https://msdn.microsoft.com/en-us/robotics/default.aspx" 
    Duration="00:00:20" />] ]>
  </Event>
  <Event time="00:00:10">
    <![CDATA[<Clip Id="{3E5169F0-A08A-4c31-BBAD-5ED51C2BAD21}" 
    Uri="http://localhost/ProgDownload/Amazon_1080.wmv" 
    ClickThruUri="http://en.wikipedia.org/wiki/Amazon_Rainforest" 
    Duration="00:00:25"/>] ]>
  </Event>     
</ContentTrack>

Para cada clipe ser agendado é um URI para o conteúdo, um URI para uma página da Web o usuário pode navegar para como uma solução cliques sobre o clipe e uma duração de reprodução para o clipe. O atributo de tempo no elemento Event Especifica onde na linha de tempo no clipe está agendado.

Você pode transformar esses dados e adicionar o fluxo de texto correspondente no manifesto do cliente, através da mesma abordagem do LINQ consulta XML, conforme descrito na seção anterior. Como antes, o fluxo de texto é exposto ao código como uma instância StreamInfo. Em seguida, você pode usar o clipe de API no SSME de agendamento para utilizar essas informações para agendar esses clipes. Figura 9 mostra um método que agenda os clipes com base nessas informações.

Figura 9 Schduling clipes

private void ScheduleClips() {
  //get the clip data stream
  StreamInfo siAdClips = ssme.AvailableStreams.Where(
    si => si.Name == "AdClips").FirstOrDefault();

  //if we have tracks
  if (siAdClips != null && siAdClips.AvailableTracks.Count > 0) {

    //for each event in that track
    foreach (TimelineEvent te in 
      siAdClips.AvailableTracks[0].TrackData) {

      //parse the inner XML fragment
      XElement xeClipData = XElement.Parse(
        Encoding.UTF8.GetString(te.EventData, 0, 
        te.EventData.Length));

      //schedule the clip
      ssme.ScheduleClip(new ClipInformation {
        ClickThroughUrl = new Uri(
        xeClipData.Attribute("ClickThruUri").Value),
        ClipUrl = new Uri(xeClipData.Attribute("Uri").Value),
        IsSmoothStreamingSource = 
        xeClipData.Attribute("Uri").Value.ToUpper().Contains("ism"), 
        Duration = TimeSpan.Parse(xeClipData.Attribute("Duration").Value)
        },
        te.EventTime, true, //pause the timeline
        null);
    }
    //set the Clip MediaElement style
    ssme.ClipMediaElementStyle = 
      this.Resources["ClipStyle"] as Style;
  }
}

O método ScheduleClip SSME faz o agendamento real. Para cada clipe que deseja agendar, uma nova instância do tipo ClipInformation é inserida na agenda com as propriedades adequadas derivadas dos dados clipe.

Observe que clipes podem ser Streaming suavizar fontes ou outras fontes que suporte para o MediaElement do Silverlight. É importante definir a propriedade ClipInformation.IsSmoothStreamingSource corretamente para certificar-se de que o componente de jogador à direita é usado para reproduzir o clipe.

O segundo parâmetro para ScheduleClip é o tempo que deseja reproduzir o clipe. O terceiro parâmetro é usado para indicar se você deseja a linha do tempo para parar em andamento enquanto o clipe está em execução. O último parâmetro é usado para passar em quaisquer dados do usuário que serão disponibilizados com os vários manipuladores de eventos relacionadas a clipes.

Às vezes clipes precisam ser agendado em uma seqüência onde informações de hora de início são aplicadas somente ao primeiro clipe em uma seqüência e clipes subseqüentes são encadeados para que todos os clipes agendados executar check-out em uma seqüência contínua. O método ScheduleClip facilita esse recurso, como mostrado na do Figura 10.

Figura 10 usar ClipContext a cadeia agendadas clipes

private void ScheduleClips() {
  StreamInfo siAdClips = ssme.AvailableStreams.Where(
  si => si.Name == "AdClips").FirstOrDefault();

  if (siAdClips != null && siAdClips.AvailableTracks.Count > 0) {
    ClipContext clipCtx = null;
    foreach (
      TimelineEvent te in siAdClips.AvailableTracks[0].TrackData) {
      XElement xeClipData = 
        XElement.Parse(Encoding.UTF8.GetString(te.EventData, 0,
        te.EventData.Length));

      //if this is the first clip to be scheduled
      if (clipCtx == null) {
        clipCtx = ssme.ScheduleClip(new ClipInformation {
          ClickThroughUrl = new Uri(
          xeClipData.Attribute("ClickThruUri").Value),
          ClipUrl = new Uri(xeClipData.Attribute("Uri").Value),
          IsSmoothStreamingSource = 
          xeClipData.Attribute("Uri").Value.ToUpper().Contains("ism"), 
          Duration = TimeSpan.Parse(
          xeClipData.Attribute("Duration").Value)
        },
        te.EventTime, //pass in the start time for the clip
        true, null);
      }
      else { //subsequent clips
        clipCtx = ssme.ScheduleClip(new ClipInformation {
          ClickThroughUrl = new Uri(
          xeClipData.Attribute("ClickThruUri").Value),
          ClipUrl = new Uri(xeClipData.Attribute("Uri").Value),
          IsSmoothStreamingSource = 
          xeClipData.Attribute("Uri").Value.ToUpper().Contains("ism"),
          Duration = TimeSpan.Parse(
          xeClipData.Attribute("Duration").Value)
        },
        clipCtx, //clip context for the previous clip to chain
        true, null);
      }
    }
    ssme.ClipMediaElementStyle = 
      this.Resources["ClipStyle"] as Style;
  }
}

Só uso um tempo absoluto para agendar o primeiro clipe quando não houver nenhum ClipContext (em outras palavras, a variável clipCtx é nula). Cada chamada subseqüente para ScheduleClip retorna uma instância ClipContext que representa o estado agendado do clipe. O método ScheduleClip tem uma sobrecarga que aceita uma instância ClipContext em vez de uma hora inicial agendada para um clipe e que agendará o clipe para iniciar imediatamente após o clipe agendado anteriormente (representado por ClipContext passado).

Ao reproduzir os clipes agendados, SSME oculta o vídeo principal e apresenta um MediaElement para reproduzir o clipe agendado. Se você desejar personalizar esse MediaElement, você pode definir a propriedade ClipMediaElementStyle em SSME para um estilo XAML desejado.

Também há vários eventos de interesse que são gerados pelo SSME durante a reprodução de um clipe agendado. O evento ClipProgressUpdate pode ser manipulado para controlar o progresso do clipe. ClipPlaybackEventArgs.Progress é do tipo de enumeração ClipProgress, que representa o progresso do clipe no quartiles. O evento ClipProgressUpdate é gerado apenas no início e no final do clipe e nos pontos de tempo que indicam a 25 %, 50 % e % de 75 da duração do clipe. Observe que a propriedade booleana ClipContext.HasQuartileEvents indica se os eventos quartil serão gerados para um clipe. Em determinados casos, como quando a duração de um clipe não for conhecida, quartil eventos de progresso não podem ser elevados.

O evento ClipClickThrough é disparado quando o Visualizador de clica em um clipe ao exibi-lo. Se destino cliques foi criado para esse clipe, ClipEventArgs.ClipContext.ClipInformation.ClickThroughUrl expõe e você pode usar uma técnica de sua escolha (como interagir com o navegador para abrir uma janela pop-up) para abrir o recurso Web alvo com o clique - através de URL.

Você também pode usar o evento ClipError e o evento ClipStateChanged para lidar com quaisquer condições de erro e alterações de estado para o clipe, respectivamente. 

A velocidade de reprodução e a direção

SSME permite que o conteúdo em execução em diferentes velocidades e direção. A propriedade SmoothStreamingMediaElement.SupportedPlaybackRates retorna uma lista de reprodução com suporte velocidades como dois valores, onde 1.0 indica a velocidade de reprodução padrão. O beta público atual, essa lista contém os valores adicionais de 0,5, 4.0, 8.0,-4.0 e-8.0. Os valores positivos ative a reprodução na metade, 4 x e 8 x velocidades e valores negativos permitem a reprodução inversa (retroceder) 4 x e 8 x velocidade.

O método SmoothStreamingMediaElement.SetPlaybackRate pode ser chamado para definir a velocidade de reprodução a qualquer momento durante a reprodução. SetPlaybackRate aceita a velocidade de reprodução desejadas como seu único parâmetro.

Observe que controlar a velocidade de reprodução só funciona para conteúdo streaming suave — portanto, se você estiver usando SSME para executar conteúdo que está sendo baixado progressivo ou fluxo usando alguma outra técnica, SetPlaybackRate irá gerar uma exceção.

Fluxo suave Edits usando manifestos composto

Às vezes, talvez seja necessário combinar partes de várias apresentações Streaming suave em uma única apresentação composta. O cenário mais comum é usando ferramentas como rough-cut editores que permitem aos usuários especificar pontos de tempo de Markção e Mark-out em uma fonte principal produzindo clipes e, em seguida, tendo vários esses clipes de reprodução potencialmente diferentes fontes de mestre de uma maneira linear como uma única apresentação.

O recurso de manifesto composto do SSME permite fazer isso, criando um documento separado de manifesto que contém o clipe de segmentos, onde cada segmento do clipe define uma parte de uma apresentação completa delimitada pelos pontos de tempo de início e término de clipe. O maior benefício de usar essa abordagem é a capacidade de criar diferentes edições em apresentações existentes sem a necessidade de transcodificar o material de origem.

Um manifesto composto sempre termina com a extensão .csm. Para consumir esse um manifesto você simplesmente definir a SmoothStreamingSource propriedade para uma URL válida apontando para um arquivo de manifesto composto:

ssme.SmoothStreamingSource = new Uri("http://localhost/SmoothStreaming/Media/MyCompositeSample.csm");

Figura 11 mostra um trecho de um manifesto composto. (O arquivo inteiro é incluído no código para download deste artigo.)

Figura 11 Sample composto manifest

<?xml version="1.0" encoding="utf-8"?>
<SmoothStreamingMedia MajorVersion="2" MinorVersion="0" Duration="269000000">
<Clip Url="http://localhost/SmoothStreaming/Media/AmazingCaves/Amazing_Caves_1080.ism/manifest" 
  ClipBegin="81000000" ClipEnd="250000000">
<StreamIndex Type="video" Chunks="9" QualityLevels="3"
  MaxWidth="992" MaxHeight="560"
  DisplayWidth="992" DisplayHeight="560"
  Url="QualityLevels({bitrate})/Fragments(video={start time})">
  <QualityLevel Index="0" Bitrate="2056000" FourCC="WVC1"
    MaxWidth="992" MaxHeight="560"
    CodecPrivateData="250000010FD37E1EF1178A1EF845E8049081BEBE7D7CC00000010E5A67F840" 
  />
  <QualityLevel Index="1" Bitrate="1427000" FourCC="WVC1"
    MaxWidth="768" MaxHeight="432"
    CodecPrivateData="250000010FCB6C17F0D78A17F835E8049081AB8BD718400000010E5A67F840" 
  />
  <QualityLevel Index="2" Bitrate="991000" FourCC="WVC1"
    MaxWidth="592" MaxHeight="332"
    CodecPrivateData="250000010FCB5E1270A58A127829680490811E3DF8F8400000010E5A67F840" 
  />
  <c t="80130000" />
  <c t="100150000" />
  <c t="120170000" />
  <c t="140190000" />
  <c t="160210000" />
  <c t="180230000" />
  <c t="200250000" />
  <c t="220270000" />
  <c t="240290000" d="20020000" />
</StreamIndex>
<StreamIndex Type="audio" Index="0" FourCC="WMAP"
  Chunks="10" QualityLevels="1" 
  Url="QualityLevels({bitrate})/Fragments(audio={start time})">
  <QualityLevel Bitrate="64000" SamplingRate="44100"
    Channels="2" BitsPerSample="16" PacketSize="2973"
    AudioTag="354" CodecPrivateData="1000030000000000000000000000E00042C0" />
  <c t="63506576" />
  <c t="81734240" />
  <c t="102632199" />
  <c t="121672562" />
  <c t="142106122" />
  <c t="162075283" />
  <c t="181580045" />
  <c t="202478004" />
  <c t="222447165" />
  <c t="241313378" d="20143311" />
</StreamIndex>
</Clip>
<Clip Url="http://localhost/SmoothStreaming/Media/CoralReef/Coral_Reef_Adventure_1080.ism/manifest" 
  ClipBegin="102000000" ClipEnd="202000000">
<StreamIndex Type="video" Chunks="6" QualityLevels="3"
  MaxWidth="992" MaxHeight="560"
  DisplayWidth="992" DisplayHeight="560"
  Url="QualityLevels({bitrate})/Fragments(video={start time})">
...
</Clip>
</SmoothStreamingMedia>

Esse manifesto contém dois elementos Media, cada um clipe (também chamado de uma edição) de definição de uma apresentação existente Streaming suave. Os pontos de atributo URL para uma apresentação existente fluxo suave e os atributos ClipBegin e ClipEnd contêm o início e término valores de tempo que fornecem os limites para o clipe. O atributo Duration no elemento de nível superior SmoothStreamingMedia precisa ser a soma exata das durações de cada clipe no manifesto — você pode somar a diferença dos valores ClipEnd e ClipBegin de cada entrada Media para obter a duração total de manifesto.

Cada elemento Media contém o vídeo e arquivos (.ismc) das apresentações de origem de manifesto StreamIndex áudio e suas entradas de QualityLevel filho, o cliente de espelhamento. No entanto, as entradas de metadados (c) do bloco para cada entrada StreamIndex, podem ser limitadas para esses blocos são necessários para satisfazer os limites ClipBegin e ClipEnd. Em outras palavras, o valor ClipBegin deve ser maior ou igual para o valor de tempo (t atributo) do início da primeira entrada c para o fluxo e ClipEnd valor precisa ser menor ou igual à soma da hora de início e nos valores de duração (atributo d) da última entrada c desse fluxo.

Observe que, em seu manifesto do cliente, blocos podem ser definidos de modo indexado (atributo n) com durações especificadas. No entanto, para obter o manifesto de composição, as partes precisam ser definidos usando seus horários de início (que podem facilmente ser calculados somando as durações das partes anteriores). Observe também que o atributo trechos em cada entrada StreamIndex precisa refletir o número de blocos no clipe, mas todos os outros atributos espelham as entradas no manifesto de cliente de origem.

Fluxos ao vivo

SSME pode reproduzir fluxos sob demanda e ao vivo. Para reproduzir um fluxo suave vídeo fluxo ao vivo usando SSME, você pode definir a propriedade SmoothStreamingSource em SSME para uma URL de ponto de publicação ao vivo:

ssme.SmoothStreamingSource = "http://localhost/SmoothStreaming/Media/FighterPilotLive.isml/manifest";

Para saber se SSME estiver sendo reproduzido um fluxo ao vivo, você pode verificar a propriedade IsLive, que é definida como True se o conteúdo é uma origem ao vivo e FALSO caso contrário.

Observe que o programa de instalação e a entrega de streaming suave ao vivo vídeo requer a infra-estrutura especializado. Uma discussão detalhada sobre como configurar um ambiente de servidor de fluxo contínuo ao vivo está além do escopo deste artigo. Você pode consultar os artigos em learn.iis.net/page.aspx/628/live-smooth-streaming/ de para obter mais detalhes sobre como configurar o IIS Media Services 3.0 para transmissão ao vivo. O artigo em learn.iis.net/page.aspx/620/live-smooth-streaming-for-iis-70---getting-started/ lhe fornecerá informações sobre como configurar uma simulação de um ambiente de fluxo contínuo ao vivo para fins de teste.

Resumindo

Streaming suave do IIS é uma plataforma de fluxo contínuo adaptável de última geração da Microsoft. Como você pôde ver, a suavizar PDK Streaming (e, em particular do tipo SmoothStreamingMediaElement) é um ingrediente essencial para os clientes do Silverlight que podem consumir fluxos sob demanda e ao vivo de criação. O PDK oferece controle abrangente o comportamento do lado do cliente de fluxos suaves e permite que você escreva rich e experiências de imersão que vão além do somente áudio/vídeo fluxos, permitindo que você facilmente combinam fluxos de dados com sua mídia de maneira significativa.

Um tratamento detalhado de streaming suave está além do escopo deste artigo. Você é incentivados a encontrar mais detalhes no iis. NET/mídia. Para obter orientação na mídia de programação no Silverlight e o tipo de MediaElement do Silverlight, você pode visitar silverlight.net/getstarted .

 

Jit Ghosh é um divulgador arquiteto na equipe do Developer Evangelism na Microsoft, avisando os clientes do mercado de mídia sobre a criação de soluções de mídia digital de alta qualidade. Ghosh é co-autor do livro de receitas de Silverlight “ ” (APress 2009). Você pode ler seu blog em blogs.msdn.com/jitghosh.

Graças ao especialista técnico seguir para revisar este artigo: Vishal Sood