Transmisja strumieniowa na żywo korzystająca z usługi Azure Media Services do tworzenia strumieni o wielokrotnej szybkości transmisji bitów z użyciem programu .NETHow to perform live streaming using Azure Media Services to create multi-bitrate streams with .NET

logo usługi Media Servicesmedia services logo


Uwaga

Do wykonania kroków tego samouczka potrzebne jest konto platformy Azure. Aby uzyskać szczegółowe informacje, zobacz Bezpłatna wersja próbna platformy Azure.

OmówienieOverview

Ten samouczek przedstawia tworzenie kanału, który odbiera strumień na żywo o pojedynczej szybkości transmisji bitów i koduje go jako strumień o wielokrotnej szybkości transmisji bitów.This tutorial walks you through the steps of creating a Channel that receives a single-bitrate live stream and encodes it to multi-bitrate stream.

Aby uzyskać więcej informacji o pojęciach związanych z kanałami obsługującymi kodowanie na żywo, zobacz temat Korzystanie z usługi Azure Media Services do prowadzenia transmisji strumieniowych na żywo ze strumieniami o wielokrotnej szybkości transmisji bitów.For more conceptual information related to Channels that are enabled for live encoding, see Live streaming using Azure Media Services to create multi-bitrate streams.

Typowy scenariusz transmisji strumieniowej na żywoCommon Live Streaming Scenario

W poniższych krokach opisano zadania związane z tworzeniem typowych aplikacji transmisji strumieniowej na żywo.The following steps describe tasks involved in creating common live streaming applications.

Uwaga

Obecnie maksymalny zalecany czas trwania wydarzenia na żywo wynosi 8 godzin.Currently, the max recommended duration of a live event is 8 hours. Napisz na adres amshelp@microsoft.com, jeśli potrzebujesz uruchomić kanał na dłuższy czas.Please contact amshelp@microsoft.com if you need to run a Channel for longer periods of time.

  1. Podłącz kamerę wideo do komputera.Connect a video camera to a computer. Uruchom i skonfiguruj lokalny koder na żywo, który wysyła strumień o pojedynczej szybkości transmisji bitów przy użyciu jednego z następujących protokołów: RTMP lub Smooth Streaming.Launch and configure an on-premises live encoder that can output a single bitrate stream in one of the following protocols: RTMP or Smooth Streaming. Aby uzyskać więcej informacji, zobacz temat Obsługa protokołu RTMP i kodery na żywo w usłudze Azure Media Services.For more information, see Azure Media Services RTMP Support and Live Encoders.

    Ten krok można również wykonać po utworzeniu kanału.This step could also be performed after you create your Channel.

  2. Utwórz i uruchom kanał.Create and start a Channel.

  3. Pobierz adres URL pozyskiwania kanału.Retrieve the Channel ingest URL.

    Koder na żywo używa adresu URL pozyskiwania do wysyłania strumienia do kanału.The ingest URL is used by the live encoder to send the stream to the Channel.

  4. Pobierz adres URL podglądu kanału.Retrieve the Channel preview URL.

    Użyj tego adresu URL, aby sprawdzić, czy kanał prawidłowo odbiera strumień na żywo.Use this URL to verify that your channel is properly receiving the live stream.

  5. Utwórz zasób.Create an asset.

  6. Aby zasób był dynamicznie szyfrowany podczas odtwarzania , należy wykonać następujące czynności:If you want for the asset to be dynamically encrypted during playback, do the following:

  7. Utwórz klucz zawartości.Create a content key.

  8. Skonfiguruj zasady autoryzacji klucza zawartości.Configure the content key's authorization policy.

  9. Skonfiguruj zasady dostarczania zasobu (stosowane podczas pakowania dynamicznego i szyfrowania dynamicznego).Configure asset delivery policy (used by dynamic packaging and dynamic encryption).

  10. Utwórz program i określ użycie utworzonego zasobu.Create a program and specify to use the asset that you created.

  11. Opublikuj zasób skojarzony z programem przez utworzenie lokalizatora OnDemand.Publish the asset associated with the program by creating an OnDemand locator.

    Uwaga

    Po utworzeniu konta usługi AMS zostanie do niego dodany domyślny punkt końcowy przesyłania strumieniowego mający stan Zatrzymany.When your AMS account is created a default streaming endpoint is added to your account in the Stopped state. Punkt końcowy przesyłania strumieniowego, z którego chcesz strumieniowo przesyłać zawartość, musi mieć stan Uruchomiony.The streaming endpoint from which you want to stream content has to be in the Running state.

  12. Uruchom program, gdy wszystko będzie gotowe do rozpoczęcia przesyłania strumieniowego i archiwizacji.Start the program when you are ready to start streaming and archiving.

  13. Opcjonalnie można przesłać do kodera na żywo sygnał o rozpoczęciu reklamy.Optionally, the live encoder can be signaled to start an advertisement. Reklama jest wstawiana do strumienia wyjściowego.The advertisement is inserted in the output stream.

  14. Zatrzymaj program w dowolnym momencie, w którym chcesz zatrzymać przesyłanie strumieniowe i archiwizowanie wydarzenia.Stop the program whenever you want to stop streaming and archiving the event.

  15. Usuń program (opcjonalnie można również usunąć zasób).Delete the Program (and optionally delete the asset).

ZawartośćWhat you'll learn

W tym artykule opisano sposób wykonywania różnych operacji na kanałach i programach przy użyciu zestawu SDK .NET usługi Media Services.This article shows you how to execute different operations on channels and programs using Media Services .NET SDK. Ponieważ czas trwania wielu operacji jest długi, użyto interfejsów API platformy .NET służących do zarządzania operacjami długotrwałymi.Because many operations are long-running .NET APIs that manage long running operations are used.

W artykule przedstawiono sposób wykonywania następujących czynności:The article shows how to do the following:

  1. Tworzenie i uruchamianie kanału.Create and start a channel. Używane są interfejsy API do operacji długotrwałych.Long-running APIs are used.
  2. Pobieranie punktu końcowego odbioru (wejścia) kanału.Get the channels ingest (input) endpoint. Ten punkt końcowy należy przekazać do kodera, który może wysyłać strumień na żywo o pojedynczej szybkości transmisji bitów.This endpoint should be provided to the encoder that can send a single bitrate live stream.
  3. Pobieranie punktu końcowego podglądu.Get the preview endpoint. Ten punkt końcowy jest używany do podglądu strumienia.This endpoint is used to preview your stream.
  4. Tworzenie zasobu używanego do przechowywania zawartości.Create an asset that is used to store your content. Należy również skonfigurować zasady dostarczania zasobów zgodnie z tym przykładem.The asset delivery policies should be configured as well, as shown in this example.
  5. Tworzenie programu i określanie użycia wcześniej utworzonego zasobu.Create a program and specify to use the asset that was created earlier. Uruchamianie programu.Start the program. Używane są interfejsy API do operacji długotrwałych.Long-running APIs are used.
  6. Tworzenie lokalizatora dla zasobu, tak aby zawartość została opublikowana i mogła być przesłana strumieniowo do klientów.Create a locator for the asset, so the content gets published and can be streamed to your clients.
  7. Wyświetlanie i ukrywanie plansz.Show and hide slates. Uruchamianie i zatrzymywanie anonsów.Start and stop advertisements. Używane są interfejsy API do operacji długotrwałych.Long-running APIs are used.
  8. Czyszczenie kanału i wszystkich skojarzonych zasobów.Clean up your channel and all the associated resources.

Wymagania wstępnePrerequisites

Następujące elementy są wymagane do wykonania czynności przedstawionych w samouczku.The following are required to complete the tutorial.

  • Konto platformy Azure.An Azure account. Jeśli nie masz konta, możesz utworzyć bezpłatne konto próbne w zaledwie kilka minut.If you don't have an account, you can create a free trial account in just a couple of minutes. Aby uzyskać szczegółowe informacje, zobacz Bezpłatna wersja próbna platformy Azure.For details, see Azure Free Trial. Otrzymasz środki, które możesz wykorzystać do wypróbowania płatnych usług Azure.You get credits that can be used to try out paid Azure services. Nawet po wyczerpaniu kredytu możesz zachować konto i korzystać z bezpłatnych usług i funkcji platformy Azure, takich jak funkcja Web Apps w usłudze Azure App Service.Even after the credits are used up, you can keep the account and use free Azure services and features, such as the Web Apps feature in Azure App Service.
  • Konto usługi Media Services.A Media Services account. Aby utworzyć konto usługi Media Services, zobacz temat Tworzenie konta.To create a Media Services account, see Create Account.
  • Visual Studio 2010 z dodatkiem SP1 (Professional, Premium, Ultimate lub Express) lub nowszy.Visual Studio 2010 SP1 (Professional, Premium, Ultimate, or Express) or later versions.
  • Należy użyć zestawu .NET SDK usługi Media Services w wersji 3.2.0.0 lub nowszej.You must use Media Services .NET SDK version 3.2.0.0 or newer.
  • Kamera internetowa i koder, który może wysyłać strumień na żywo o pojedynczej szybkości transmisji bitów.A webcam and an encoder that can send a single bitrate live stream.

Zagadnienia do rozważeniaConsiderations

  • Obecnie maksymalny zalecany czas trwania wydarzenia na żywo wynosi 8 godzin.Currently, the max recommended duration of a live event is 8 hours. Napisz na adres amshelp@microsoft.com, jeśli potrzebujesz uruchomić kanał na dłuższy czas.Please contact amshelp@microsoft.com if you need to run a Channel for longer periods of time.
  • Limit różnych zasad usługi AMS wynosi 1 000 000 (na przykład zasad lokalizatorów lub ContentKeyAuthorizationPolicy).There is a limit of 1,000,000 policies for different AMS policies (for example, for Locator policy or ContentKeyAuthorizationPolicy). Należy używać tego samego identyfikatora zasad, jeśli zawsze są używane uprawnienia dotyczące tych samych dni lub tego samego dostępu, na przykład dla lokalizatorów przeznaczonych do długotrwałego stosowania (nieprzekazywanych zasad).You should use the same policy ID if you are always using the same days / access permissions, for example, policies for locators that are intended to remain in place for a long time (non-upload policies). Aby uzyskać więcej informacji, zobacz ten artykuł.For more information, see this article.

Pobieranie przykładuDownload sample

Przykład opisany w tym artykule możesz pobrać tutaj.You can download the sample that is described in this article from here.

Konfigurowanie środowiska deweloperskiego przy użyciu zestawu .NET SDK usługi Media ServicesSet up for development with Media Services SDK for .NET

Skonfiguruj środowisko projektowe i wypełnij plik app.config przy użyciu informacji dotyczących połączenia, zgodnie z opisem w sekcji Projektowanie usługi Media Services na platformie .NET.Set up your development environment and populate the app.config file with connection information, as described in Media Services development with .NET.

Przykładowy kodCode example

using System;
using System.Collections.Generic;
using System.Configuration;
using System.IO;
using System.Linq;
using System.Net;
using Microsoft.WindowsAzure.MediaServices.Client;
using Microsoft.WindowsAzure.MediaServices.Client.DynamicEncryption;

namespace EncodeLiveStreamWithAmsClear
{
    class Program
    {
        private const string ChannelName = "channel001";
        private const string AssetName = "asset001";
        private const string ProgramName = "program001";

        // Read values from the App.config file.
        private static readonly string _AADTenantDomain =
            ConfigurationManager.AppSettings["AMSAADTenantDomain"];
        private static readonly string _RESTAPIEndpoint =
            ConfigurationManager.AppSettings["AMSRESTAPIEndpoint"];
        private static readonly string _AMSClientId =
            ConfigurationManager.AppSettings["AMSClientId"];
        private static readonly string _AMSClientSecret =
            ConfigurationManager.AppSettings["AMSClientSecret"];

        private static CloudMediaContext _context = null;

        static void Main(string[] args)
        {
            AzureAdTokenCredentials tokenCredentials =
                new AzureAdTokenCredentials(_AADTenantDomain,
                    new AzureAdClientSymmetricKey(_AMSClientId, _AMSClientSecret),
                    AzureEnvironments.AzureCloudEnvironment);

            var tokenProvider = new AzureAdTokenProvider(tokenCredentials);

            _context = new CloudMediaContext(new Uri(_RESTAPIEndpoint), tokenProvider);

            IChannel channel = CreateAndStartChannel();

            // The channel's input endpoint:
            string ingestUrl = channel.Input.Endpoints.FirstOrDefault().Url.ToString();

            Console.WriteLine("Intest URL: {0}", ingestUrl);


            // Use the previewEndpoint to preview and verify 
            // that the input from the encoder is actually reaching the Channel. 
            string previewEndpoint = channel.Preview.Endpoints.FirstOrDefault().Url.ToString();

            Console.WriteLine("Preview URL: {0}", previewEndpoint);

            // When Live Encoding is enabled, you can now get a preview of the live feed as it reaches the Channel. 
            // This can be a valuable tool to check whether your live feed is actually reaching the Channel. 
            // The thumbnail is exposed via the same end-point as the Channel Preview URL.
            string thumbnailUri = new UriBuilder
            {
                Scheme = Uri.UriSchemeHttps,
                Host = channel.Preview.Endpoints.FirstOrDefault().Url.Host,
                Path = "thumbnails/input.jpg"
            }.Uri.ToString();

            Console.WriteLine("Thumbain URL: {0}", thumbnailUri);

            // Once you previewed your stream and verified that it is flowing into your Channel, 
            // you can create an event by creating an Asset, Program, and Streaming Locator. 
            IAsset asset = CreateAndConfigureAsset();

            IProgram program = CreateAndStartProgram(channel, asset);

            ILocator locator = CreateLocatorForAsset(program.Asset, program.ArchiveWindowLength);

            // You can use slates and ads only if the channel type is Standard.  
            StartStopAdsSlates(channel);

            // Once you are done streaming, clean up your resources.
            Cleanup(channel);
        }

        public static IChannel CreateAndStartChannel()
        {
            var channelInput = CreateChannelInput();
            var channelPreview = CreateChannelPreview();
            var channelEncoding = CreateChannelEncoding();

            ChannelCreationOptions options = new ChannelCreationOptions
            {
                EncodingType = ChannelEncodingType.Standard,
                Name = ChannelName,
                Input = channelInput,
                Preview = channelPreview,
                Encoding = channelEncoding
            };

            Log("Creating channel");
            IOperation channelCreateOperation = _context.Channels.SendCreateOperation(options);
            string channelId = TrackOperation(channelCreateOperation, "Channel create");

            IChannel channel = _context.Channels.FirstOrDefault(c => c.Id == channelId);

            Log("Starting channel");
            var channelStartOperation = channel.SendStartOperation();
            TrackOperation(channelStartOperation, "Channel start");

            return channel;
        }

        /// <summary>
        /// Create channel input, used in channel creation options. 
        /// </summary>
        /// <returns></returns>
        private static ChannelInput CreateChannelInput()
        {
            // When creating a Channel, you can specify allowed IP addresses in one of the following formats: 
            // IpV4 address with 4 numbers
            // CIDR address range

            return new ChannelInput
            {
                StreamingProtocol = StreamingProtocol.FragmentedMP4,
                AccessControl = new ChannelAccessControl
                {
                    IPAllowList = new List<IPRange>
                    {
                        new IPRange
                        {
                        Name = "TestChannelInput001",
                        Address = IPAddress.Parse("0.0.0.0"),
                        SubnetPrefixLength = 0
                        }
                    }
                }
            };
        }

        /// <summary>
        /// Create channel preview, used in channel creation options. 
        /// </summary>
        /// <returns></returns>
        private static ChannelPreview CreateChannelPreview()
        {
            // When creating a Channel, you can specify allowed IP addresses in one of the following formats: 
            // IpV4 address with 4 numbers
            // CIDR address range

            return new ChannelPreview
            {
                AccessControl = new ChannelAccessControl
                {
                    IPAllowList = new List<IPRange>
                {
                    new IPRange
                    {
                    Name = "TestChannelPreview001",
                    Address = IPAddress.Parse("0.0.0.0"),
                    SubnetPrefixLength = 0
                    }
                }
                }
            };
        }

        /// <summary>
        /// Create channel encoding, used in channel creation options. 
        /// </summary>
        /// <returns></returns>
        private static ChannelEncoding CreateChannelEncoding()
        {
            return new ChannelEncoding
            {
                SystemPreset = "Default720p",
                IgnoreCea708ClosedCaptions = false,
                AdMarkerSource = AdMarkerSource.Api
            };
        }

        /// <summary>
        /// Create an asset and configure asset delivery policies.
        /// </summary>
        /// <returns></returns>
        public static IAsset CreateAndConfigureAsset()
        {
            IAsset asset = _context.Assets.Create(AssetName, AssetCreationOptions.None);

            IAssetDeliveryPolicy policy =
            _context.AssetDeliveryPolicies.Create("Clear Policy",
            AssetDeliveryPolicyType.NoDynamicEncryption,
            AssetDeliveryProtocol.HLS | AssetDeliveryProtocol.SmoothStreaming | AssetDeliveryProtocol.Dash, null);

            asset.DeliveryPolicies.Add(policy);

            return asset;
        }

        /// <summary>
        /// Create a Program on the Channel. You can have multiple Programs that overlap or are sequential;
        /// however each Program must have a unique name within your Media Services account.
        /// </summary>
        /// <param name="channel"></param>
        /// <param name="asset"></param>
        /// <returns></returns>
        public static IProgram CreateAndStartProgram(IChannel channel, IAsset asset)
        {
            IProgram program = channel.Programs.Create(ProgramName, TimeSpan.FromHours(3), asset.Id);
            Log("Program created", program.Id);

            Log("Starting program");
            var programStartOperation = program.SendStartOperation();
            TrackOperation(programStartOperation, "Program start");

            return program;
        }

        /// <summary>
        /// Create locators in order to be able to publish and stream the video.
        /// </summary>
        /// <param name="asset"></param>
        /// <param name="ArchiveWindowLength"></param>
        /// <returns></returns>
        public static ILocator CreateLocatorForAsset(IAsset asset, TimeSpan ArchiveWindowLength)
        {
            // You cannot create a streaming locator using an AccessPolicy that includes write or delete permissions.            
            var locator = _context.Locators.CreateLocator
            (
                LocatorType.OnDemandOrigin,
                asset,
                _context.AccessPolicies.Create
                (
                    "Live Stream Policy",
                    ArchiveWindowLength,
                    AccessPermissions.Read
                )
            );

            return locator;
        }

        /// <summary>
        /// Perform operations on slates.
        /// </summary>
        /// <param name="channel"></param>
        public static void StartStopAdsSlates(IChannel channel)
        {
            int cueId = new Random().Next(int.MaxValue);
            var path = Path.GetFullPath(Path.Combine(AppDomain.CurrentDomain.BaseDirectory, @"..\\..\\SlateJPG\\DefaultAzurePortalSlate.jpg"));

            Log("Creating asset");
            var slateAsset = _context.Assets.Create("Slate test asset " + DateTime.Now.ToString("yyyy-MM-dd HH-mm"), AssetCreationOptions.None);
            Log("Slate asset created", slateAsset.Id);

            Log("Uploading file");
            var assetFile = slateAsset.AssetFiles.Create("DefaultAzurePortalSlate.jpg");
            assetFile.Upload(path);
            assetFile.IsPrimary = true;
            assetFile.Update();

            Log("Showing slate");
            var showSlateOperation = channel.SendShowSlateOperation(TimeSpan.FromMinutes(1), slateAsset.Id);
            TrackOperation(showSlateOperation, "Show slate");

            Log("Hiding slate");
            var hideSlateOperation = channel.SendHideSlateOperation();
            TrackOperation(hideSlateOperation, "Hide slate");

            Log("Starting ad");
            var startAdOperation = channel.SendStartAdvertisementOperation(TimeSpan.FromMinutes(1), cueId, false);
            TrackOperation(startAdOperation, "Start ad");

            Log("Ending ad");
            var endAdOperation = channel.SendEndAdvertisementOperation(cueId);
            TrackOperation(endAdOperation, "End ad");

            Log("Deleting slate asset");
            slateAsset.Delete();
        }

        /// <summary>
        /// Clean up resources associated with the channel.
        /// </summary>
        /// <param name="channel"></param>
        public static void Cleanup(IChannel channel)
        {
            IAsset asset;
            if (channel != null)
            {
                foreach (var program in channel.Programs)
                {
                    asset = _context.Assets.FirstOrDefault(se => se.Id == program.AssetId);

                    Log("Stopping program");
                    var programStopOperation = program.SendStopOperation();
                    TrackOperation(programStopOperation, "Program stop");

                    program.Delete();

                    if (asset != null)
                    {
                        Log("Deleting locators");
                        foreach (var l in asset.Locators)
                            l.Delete();

                        Log("Deleting asset");
                        asset.Delete();
                    }
                }

                Log("Stopping channel");
                var channelStopOperation = channel.SendStopOperation();
                TrackOperation(channelStopOperation, "Channel stop");

                Log("Deleting channel");
                var channelDeleteOperation = channel.SendDeleteOperation();
                TrackOperation(channelDeleteOperation, "Channel delete");
            }
        }

        /// <summary>
        /// Track long running operations.
        /// </summary>
        /// <param name="operation"></param>
        /// <param name="description"></param>
        /// <returns></returns>
        public static string TrackOperation(IOperation operation, string description)
        {
            string entityId = null;
            bool isCompleted = false;

            Log("starting to track ", null, operation.Id);
            while (isCompleted == false)
            {
                operation = _context.Operations.GetOperation(operation.Id);
                isCompleted = IsCompleted(operation, out entityId);
                System.Threading.Thread.Sleep(TimeSpan.FromSeconds(30));
            }
            // If we got here, the operation succeeded.
            Log(description + " in completed", operation.TargetEntityId, operation.Id);

            return entityId;
        }

        /// <summary> 
        /// Checks if the operation has been completed. 
        /// If the operation succeeded, the created entity Id is returned in the out parameter.
        /// </summary> 
        /// <param name="operationId">The operation Id.</param> 
        /// <param name="channel">
        /// If the operation succeeded, 
        /// the entity Id associated with the successful operation is returned in the out parameter.</param>
        /// <returns>Returns false if the operation is still in progress; otherwise, true.</returns> 
        private static bool IsCompleted(IOperation operation, out string entityId)
        {
            bool completed = false;

            entityId = null;

            switch (operation.State)
            {
                case OperationState.Failed:
                    // Handle the failure. 
                    // For example, throw an exception. 
                    // Use the following information in the exception: operationId, operation.ErrorMessage.
                    Log("operation failed", operation.TargetEntityId, operation.Id);
                    break;
                case OperationState.Succeeded:
                    completed = true;
                    entityId = operation.TargetEntityId;
                    break;
                case OperationState.InProgress:
                    completed = false;
                    Log("operation in progress", operation.TargetEntityId, operation.Id);
                    break;
            }
            return completed;
        }

        private static void Log(string action, string entityId = null, string operationId = null)
        {
            Console.WriteLine(
            "{0,-21}{1,-51}{2,-51}{3,-51}",
            DateTime.Now.ToString("yyyy'-'MM'-'dd HH':'mm':'ss"),
            action,
            entityId ?? string.Empty,
            operationId ?? string.Empty);
        }
    }
}

Następny krokNext step

Przejrzyj ścieżki szkoleniowe dotyczące usługi Media Services.Review Media Services learning paths.

Azure Media Services w wersji 3 (najnowsza)Media Services v3 (latest)

Zapoznaj się z najnowszą wersją Azure Media Services.Check out the latest version of Azure Media Services!

Media Services w wersji 2 (starsza wersja)Media Services v2 (legacy)

Wyraź opinięProvide feedback

Skorzystaj z forum User Voice, aby przekazać opinie i sugestie dotyczące sposobów usprawnienia usługi Azure Media Services.Use the User Voice forum to provide feedback and make suggestions on how to improve Azure Media Services. Możesz także przejść bezpośrednio do jednej z następujących kategorii:You also can go directly to one of the following categories: