教程:使用媒体服务进行实时流式传输Tutorial: Stream live with Media Services

备注

尽管本教程使用了 .NET SDK 示例,但 REST APICLI 或其他受支持的 SDK 的常规步骤是相同的。Even though the tutorial uses .NET SDK examples, the general steps are the same for REST API, CLI, or other supported SDKs.

在 Azure 媒体服务中,直播活动负责处理实时传送视频流内容。In Azure Media Services, Live Events are responsible for processing live streaming content. 直播活动提供输入终结点(引入 URL),然后由你将该终结点提供给实时编码器。A Live Event provides an input endpoint (ingest URL) that you then provide to a live encoder. 直播活动从实时编码器接收实时输入流,并通过一个或多个流式处理终结点使其可用于流式处理。The Live Event receives live input streams from the live encoder and makes it available for streaming through one or more Streaming Endpoints. 直播活动还提供可用于预览的预览终结点(预览 URL),并在进一步处理和传递流之前对流进行验证。Live Events also provide a preview endpoint (preview URL) that you use to preview and validate your stream before further processing and delivery. 本教程演示如何使用 .NET Core 创建直通类型的直播活动。This tutorial shows how to use .NET Core to create a pass-through type of a live event.

本教程介绍如何:The tutorial shows you how to:

  • 下载本主题中所述的示例应用。Download the sample app described in the topic.
  • 检查执行实时传送视频流的代码。Examine the code that performs live streaming.
  • 使用 Azure Media Player 在 https://ampdemo.azureedge.net 观看事件。Watch the event with Azure Media Player at https://ampdemo.azureedge.net.
  • 清理资源。Clean up resources.

如果没有 Azure 订阅,可在开始前创建一个试用帐户If you don't have an Azure subscription, create a trial account before you begin.

先决条件Prerequisites

以下项目是完成本教程所需具备的条件:The following items are required to complete the tutorial:

  • 安装 Visual Studio Code 或 Visual Studio。Install Visual Studio Code or Visual Studio.
  • 创建媒体服务帐户Create a Media Services account.
    请务必记住用于资源组名称和媒体服务帐户名称的值。Make sure to remember the values you use for the resource group name and Media Services account name.
  • 遵循使用 Azure CLI 访问 Azure 媒体服务 API 中的步骤并保存凭据。Follow the steps in Access Azure Media Services API with the Azure CLI and save the credentials. 你将需要使用这些凭据来访问 API。You'll need to use them to access the API.
  • 一个用于广播事件的相机或设备(例如便携式计算机)。A camera or a device (like a laptop) that's used to broadcast an event.
  • 一个本地实时编码器,用于将来自相机的信号转换为发送到媒体服务实时传送视频流服务的流,请参阅建议的本地实时编码器An on-premises live encoder that converts signals from the camera to streams that are sent to the Media Services live streaming service, see recommended on-premises live encoders. 流必须为 RTMP 或“平滑流式处理” 格式。The stream has to be in RTMP or Smooth Streaming format.

提示

确保在继续操作之前查看使用媒体服务 v3 的实时传送视频流Make sure to review Live streaming with Media Services v3 before proceeding.

下载并配置示例Download and configure the sample

使用以下命令将包含流式处理 .NET 示例的 GitHub 存储库克隆到计算机:Clone a GitHub repository that contains the streaming .NET sample to your machine using the following command:

git clone https://github.com/Azure-Samples/media-services-v3-dotnet-core-tutorials.git

实时传送视频流示例位于 Live 文件夹中。The live streaming sample is located in the Live folder.

打开下载的项目中的 appsettings.jsonOpen appsettings.json in your downloaded project. 将值替换为从访问 API 获得的凭据。Replace the values with the credentials you got from accessing APIs.

重要

此示例为每个资源使用唯一的后缀。This sample uses a unique suffix for each resource. 如果取消调试操作或者中途终止应用,则帐户中会有多个直播活动。If you cancel the debugging or terminate the app without running it through, you'll end up with multiple Live Events in your account.
请务必停止正在运行的直播活动,Make sure to stop the running Live Events. 否则,将会对你“收费” !Otherwise, you'll be billed!

检查执行实时传送视频流的代码Examine the code that performs live streaming

此部分讨论 MediaV3LiveApp 项目的 Program.cs 文件中定义的函数 。This section examines functions defined in the Program.cs file of the MediaV3LiveApp project.

此示例为每个资源创建唯一的后缀,因此即使在没有清理的情况下运行示例多次,也不会有名称冲突。The sample creates a unique suffix for each resource so that you don't have name collisions if you run the sample multiple times without cleaning up.

重要

此示例为每个资源使用唯一的后缀。This sample uses a unique suffix for each resource. 如果取消调试操作或者中途终止应用,则帐户中会有多个直播活动。If you cancel the debugging or terminate the app without running it through, you'll end up with multiple Live Events in your account.
请务必停止正在运行的直播活动,Make sure to stop the running Live Events. 否则,将会对你“收费” !Otherwise, you'll be billed!

开始结合使用媒体服务 API 与 .NET SDKStart using Media Services APIs with .NET SDK

若要开始将媒体服务 API 与 .NET 结合使用,需要创建 AzureMediaServicesClient 对象 。To start using Media Services APIs with .NET, you need to create an AzureMediaServicesClient object. 若要创建对象,需要提供客户端所需凭据以使用 Azure AD 连接到 Azure。To create the object, you need to supply credentials needed for the client to connect to Azure using Azure AD. 在本文开头克隆的代码中,GetCredentialsAsync 函数根据本地配置文件中提供的凭据创建 ServiceClientCredentials 对象。In the code you cloned at the beginning of the article, the GetCredentialsAsync function creates the ServiceClientCredentials object based on the credentials supplied in local configuration file.

private static async Task<IAzureMediaServicesClient> CreateMediaServicesClientAsync(ConfigWrapper config)
{
    var credentials = await GetCredentialsAsync(config);

    return new AzureMediaServicesClient(config.ArmEndpoint, credentials)
    {
        SubscriptionId = config.SubscriptionId,
    };
}

创建直播活动Create a live event

本部分介绍如何创建直通类型的实时事件(LiveEventEncodingType 设置为 None)。This section shows how to create a pass-through type of Live Event (LiveEventEncodingType set to None). 有关实时事件的可用类型的详细信息,请参阅实时事件类型For more information about the available types of Live Events, see Live Event types.

可能需要在创建直播活动时指定的一些事项包括:Some things that you might want to specify when creating the live event are:

  • 媒体服务位置。Media Services location.
  • 直播活动的流式处理协议(目前支持 RTMP 和平滑流式处理协议)。The streaming protocol for the Live Event (currently, the RTMP and Smooth Streaming protocols are supported).
    运行直播活动或其关联的实时输出时,无法更改协议选项。You can't change the protocol option while the Live Event or its associated Live Outputs are running. 如果需要其他协议,请为每个流式处理协议创建单独的直播活动。If you require different protocols, create separate Live Event for each streaming protocol.
  • 对引入和预览的 IP 限制。IP restrictions on the ingest and preview. 可定义允许向该直播活动引入视频的 IP 地址。You can define the IP addresses that are allowed to ingest a video to this Live Event. 允许的 IP 地址可以指定为单个 IP 地址(例如“10.0.0.1”)、使用一个 IP 地址和 CIDR 子网掩码的 IP 范围(例如“10.0.0.1/22”)或使用一个 IP 地址和点分十进制子网掩码的 IP 范围(例如“10.0.0.1(255.255.252.0)”)。Allowed IP addresses can be specified as either a single IP address (for example '10.0.0.1'), an IP range using an IP address and a CIDR subnet mask (for example, '10.0.0.1/22'), or an IP range using an IP address and a dotted decimal subnet mask (for example, '10.0.0.1(255.255.252.0)').
    如果未指定 IP 地址并且没有规则定义,则不会允许任何 IP 地址。If no IP addresses are specified and there's no rule definition, then no IP address will be allowed. 若要允许任何 IP 地址,请创建规则并设置 0.0.0.0/0。To allow any IP address, create a rule and set 0.0.0.0/0.
    IP 地址必须采用以下格式之一:具有四个数字或 CIDR 地址范围的 IpV4 地址。The IP addresses have to be in one of the following formats: IpV4 address with four numbers or CIDR address range.
  • 创建事件时,可以将其启动方式指定为自动启动。When creating the event, you can specify to autostart it.
    如果将 autostart 设置为 true,则直播活动会在创建后启动。When autostart is set to true, the Live Event will be started after creation. 这意味着,只要直播活动开始运行,就会开始计费。That means the billing starts as soon as the Live Event starts running. 必须显式对直播活动资源调用停止操作才能停止进一步计费。You must explicitly call Stop on the Live Event resource to halt further billing. 有关详细信息,请参阅直播活动状态和计费For more information, see Live Event states and billing.
  • 要使引入 URL 具有预测性,请设置“vanity”模式。For an ingest URL to be predictive, set the "vanity" mode. 有关详细信息,请参阅实时事件引入 URLFor detailed information, see Live Event ingest URLs.
Console.WriteLine($"Creating a live event named {liveEventName}");
Console.WriteLine();

// Note: When creating a LiveEvent, you can specify allowed IP addresses in one of the following formats:                 
//      IpV4 address with 4 numbers
//      CIDR address range

IPRange allAllowIPRange = new IPRange(
    name: "AllowAll",
    address: "0.0.0.0",
    subnetPrefixLength: 0
);

// Create the LiveEvent input IP access control.
LiveEventInputAccessControl liveEventInputAccess = new LiveEventInputAccessControl
{
    Ip = new IPAccessControl(
            allow: new IPRange[]
            {
                allAllowIPRange
            }
        )

};

// Create the LiveEvent Preview IP access control
LiveEventPreview liveEventPreview = new LiveEventPreview
{
    AccessControl = new LiveEventPreviewAccessControl(
        ip: new IPAccessControl(
            allow: new IPRange[]
            {
                allAllowIPRange
            }
        )
    )
};

// To get the same ingest URL for the same LiveEvent name:
// 1. Set vanityUrl to true so you have ingest like: 
//        rtmps://liveevent-hevc12-eventgridmediaservice-cne21.channel.media.chinacloudapi.cn:2935/live/522f9b27dd2d4b26aeb9ef8ab96c5c77           
// 2. Set accessToken to a desired GUID string (with or without hyphen)

LiveEvent liveEvent = new LiveEvent(
    location: mediaService.Location,
    description: "Sample LiveEvent for testing",
    vanityUrl: false,
    encoding: new LiveEventEncoding(
                // When encodingType is None, the service simply passes through the incoming video and audio layer(s) to the output
                // When the encodingType is set to Standard or Premium1080p, a live encoder is used to transcode the incoming stream
                // into multiple bit rates or layers. See https://docs.azure.cn/media-services/latest/live-event-types-comparison for more information
                encodingType: LiveEventEncodingType.None,
                presetName: null
            ),
    input: new LiveEventInput(LiveEventInputProtocol.RTMP, liveEventInputAccess),
    preview: liveEventPreview,
    streamOptions: new List<StreamOptionsFlag?>()
    {
        // Set this to Default or Low Latency
        // When using Low Latency mode, you must configure the Azure Media Player to use the 
        // quick start hueristic profile or you won't notice the change. 
        // In the AMP player client side JS options, set -  heuristicProfile: "Low Latency Heuristic Profile". 
        // To use low latency optimally, you should tune your encoder settings down to 1 second GOP size instead of 2 seconds.
        StreamOptionsFlag.LowLatency
    }
);

Console.WriteLine($"Creating the LiveEvent, be patient this can take time...");

// When autostart is set to true, the Live Event will be started after creation. 
// That means, the billing starts as soon as the Live Event starts running. 
// You must explicitly call Stop on the Live Event resource to halt further billing.
// The following operation can sometimes take awhile. Be patient.
liveEvent = await client.LiveEvents.CreateAsync(config.ResourceGroup, config.AccountName, liveEventName, liveEvent, autoStart: true);

获取引入 URLGet ingest URLs

创建直播活动后,可以获得要提供给实时编码器的引入 URL。Once the Live Event is created, you can get ingest URLs that you'll provide to the live encoder. 编码器使用这些 URL 来输入实时流。The encoder uses these URLs to input a live stream.

string ingestUrl = liveEvent.Input.Endpoints.First().Url;
Console.WriteLine($"The ingest url to configure the on premise encoder with is:");
Console.WriteLine($"\t{ingestUrl}");
Console.WriteLine();

获取预览 URLGet the preview URL

使用 previewEndpoint 预览来自编码器的输入并验证其是否已确实收到。Use the previewEndpoint to preview and verify that the input from the encoder is actually being received.

重要

确保视频流向预览 URL,然后再继续操作。Make sure that the video is flowing to the Preview URL before continuing.

string previewEndpoint = liveEvent.Preview.Endpoints.First().Url;
Console.WriteLine($"The preview url is:");
Console.WriteLine($"\t{previewEndpoint}");
Console.WriteLine();

Console.WriteLine($"Open the live preview in your browser and use the Azure Media Player to monitor the preview playback:");
Console.WriteLine($"\thttps://ampdemo.azureedge.net/?url={previewEndpoint}&heuristicprofile=lowlatency");
Console.WriteLine();

创建和管理直播活动与实时输出Create and manage Live Events and Live Outputs

将流传输到实时事件后,可以通过创建资产、实时输出和流定位符来启动流式传输事件。Once you have the stream flowing into the Live Event, you can begin the streaming event by creating an Asset, Live Output, and Streaming Locator. 这会存档流,并使观看者可通过流式处理终结点使用该流。This will archive the stream and make it available to viewers through the Streaming Endpoint.

创建资产Create an Asset

创建供实时输出使用的资产。Create an Asset for the Live Output to use.

Console.WriteLine($"Creating an asset named {assetName}");
Console.WriteLine();
Asset asset = await client.Assets.CreateOrUpdateAsync(config.ResourceGroup, config.AccountName, assetName, new Asset());

创建实时输出Create a Live Output

实时输出在创建时启动,在删除后停止。Live Outputs start on creation and stop when deleted. 删除实时输出不会删除基础资产和该资产中的内容。When you delete the Live Output, you're not deleting the underlying Asset and content in the asset.

string manifestName = "output";
Console.WriteLine($"Creating a live output named {liveOutputName}");
Console.WriteLine();

LiveOutput liveOutput = new LiveOutput(assetName: asset.Name, manifestName: manifestName, archiveWindowLength: TimeSpan.FromMinutes(10));
liveOutput = await client.LiveOutputs.CreateAsync(config.ResourceGroup, config.AccountName, liveEventName, liveOutputName, liveOutput);

创建流定位符Create a Streaming Locator

备注

创建媒体服务帐户后,一个处于“已停止” 状态的“默认” 流式处理终结点会添加到帐户。When your Media Services account is created, a default streaming endpoint is added to your account in the Stopped state. 若要开始流式传输内容并利用动态打包和动态加密,要从中流式传输内容的流式处理终结点必须处于“正在运行”状态 。To start streaming your content and take advantage of dynamic packaging and dynamic encryption, the streaming endpoint from which you want to stream content has to be in the Running state.

如果已使用流定位符发布了实时输出资产,则直播活动(长达 DVR 窗口长度)将继续可见,直到流定位符过期或被删除(以先发生为准)。When you publish the Live Output asset using a Streaming Locator, the Live Event (up to the DVR window length) will continue to be viewable until the Streaming Locator's expiry or deletion, whichever comes first.

Console.WriteLine($"Creating a streaming locator named {streamingLocatorName}");
Console.WriteLine();

StreamingLocator locator = new StreamingLocator(assetName: asset.Name, streamingPolicyName: PredefinedStreamingPolicy.ClearStreamingOnly);
locator = await client.StreamingLocators.CreateAsync(config.ResourceGroup, config.AccountName, streamingLocatorName, locator);

// Get the default Streaming Endpoint on the account
StreamingEndpoint streamingEndpoint = await client.StreamingEndpoints.GetAsync(config.ResourceGroup, config.AccountName, streamingEndpointName);

// If it's not running, Start it. 
if (streamingEndpoint.ResourceState != StreamingEndpointResourceState.Running)
{
    Console.WriteLine("Streaming Endpoint was Stopped, restarting now..");
    await client.StreamingEndpoints.StartAsync (config.ResourceGroup, config.AccountName, streamingEndpointName);
}

// Get the url to stream the output
ListPathsResponse paths = await client.StreamingLocators.ListPathsAsync(resourceGroupName, accountName, locatorName);

foreach (StreamingPath path in paths.StreamingPaths)
{
    UriBuilder uriBuilder = new UriBuilder();
    uriBuilder.Scheme = "https";
    uriBuilder.Host = streamingEndpoint.HostName;

    uriBuilder.Path = path.Paths[0];
    // Get the URL from the uriBuilder: uriBuilder.ToString()
}

清理媒体服务帐户中的资源Cleaning up resources in your Media Services account

如果已完成流式处理事件,并想要清理先前设置的资源,请遵循以下过程:If you're done streaming events and want to clean up the resources provisioned earlier, follow the following procedure:

  • 停止从编码器推送流。Stop pushing the stream from the encoder.
  • 停止直播活动。Stop the Live Event. 直播活动在停止后,不会产生任何费用。Once the Live Event is stopped, it won't incur any charges. 需要重新启动它时,它会采用相同的引入 URL,因此无需重新配置编码器。When you need to start it again, it will have the same ingest URL so you won't need to reconfigure your encoder.
  • 除非想要继续以点播流形式提供直播活动的存档,否则可以停止流式处理终结点。You can stop your Streaming Endpoint, unless you want to continue to provide the archive of your live event as an on-demand stream. 如果直播活动处于停止状态,则不会产生任何费用。If the Live Event is in a stopped state, it won't incur any charges.
private static async Task CleanupLiveEventAndOutputAsync(IAzureMediaServicesClient client, string resourceGroup, string accountName, string liveEventName)
{
    try
    {
        LiveEvent liveEvent = await client.LiveEvents.GetAsync(resourceGroup, accountName, liveEventName);

        if (liveEvent != null)
        {
            if (liveEvent.ResourceState == LiveEventResourceState.Running)
            {
                // If the LiveEvent is running, stop it and have it remove any LiveOutputs
                await client.LiveEvents.StopAsync(resourceGroup, accountName, liveEventName, removeOutputsOnStop: true);
            }

            // Delete the LiveEvent
            await client.LiveEvents.DeleteAsync(resourceGroup, accountName, liveEventName);
        }
    }
    catch (ApiErrorException e)
    {
        Console.WriteLine("CleanupLiveEventAndOutputAsync -- Hit ApiErrorException");
        Console.WriteLine($"\tCode: {e.Body.Error.Code}");
        Console.WriteLine($"\tCode: {e.Body.Error.Message}");
        Console.WriteLine();
    }
}
private static async Task CleanupLocatorandAssetAsync(IAzureMediaServicesClient client, string resourceGroup, string accountName, string streamingLocatorName, string assetName)
{
    try
    {
        // Delete the Streaming Locator
        await client.StreamingLocators.DeleteAsync(resourceGroup, accountName, streamingLocatorName);

        // Delete the Archive Asset
        await client.Assets.DeleteAsync(resourceGroup, accountName, assetName);
    }
    catch (ApiErrorException e)
    {
        Console.WriteLine("CleanupLocatorandAssetAsync -- Hit ApiErrorException");
        Console.WriteLine($"\tCode: {e.Body.Error.Code}");
        Console.WriteLine($"\tCode: {e.Body.Error.Message}");
        Console.WriteLine();
    }
}

观看事件Watch the event

若要观看事件,请复制流式传输 URL(在运行“创建流定位符”中所述的代码时获得)。To watch the event, copy the streaming URL that you got when you ran code described in Create a Streaming Locator. 你可以使用所选的媒体播放器。You can use a media player of your choice. 使用 Azure Media Player 在 https://ampdemo.azureedge.net 中测试流。Azure Media Player to test your stream at https://ampdemo.azureedge.net.

直播活动在停止后会自动转换为点播内容。Live Event automatically converts events to on-demand content when stopped. 即使你停止并删除了事件,只要没有删除资产,用户也能够按需将已存档内容作为视频进行流式传输。Even after you stop and delete the event, users can stream your archived content as a video on demand for as long as you don't delete the asset. 如果资产被某个事件使用,则无法将其删除,必须先删除该事件。An asset can't be deleted if it's used by an event; the event must be deleted first.

清理资源Clean up resources

如果不再需要资源组中的任何一个资源(包括为本教程创建的媒体服务和存储帐户),请删除之前创建的资源组。If you no longer need any of the resources in your resource group, including the Media Services and storage accounts you created for this tutorial, delete the resource group you created earlier.

执行以下 CLI 命令:Execute the following CLI command:

az group delete --name amsResourceGroup

重要

让直播活动保持运行会产生费用。Leaving the Live Event running incurs billing costs. 请注意,如果项目/节目崩溃或因某种原因而关闭,可能会导致直播活动保持运行状态,从而产生费用。Be aware, if the project/program crashes or is closed out for any reason, it could leave the Live Event running in a billing state.

后续步骤Next steps

对文件进行流式处理Stream files