자습서: .NET 7.0을 사용하여 Media Services로 라이브 스트리밍

Media Services 로고 v3


경고

Azure Media Services는 2024년 6월 30일에 사용 중지됩니다. 자세한 내용은 AMS 사용 중지 가이드를 참조하세요.

Azure Media Services에서 라이브 이벤트는 라이브 스트리밍 콘텐츠 처리를 담당합니다. 라이브 이벤트는 라이브 인코더에 제공할 입력 엔드포인트(수집 URL)를 제공합니다. 라이브 이벤트는 RTMP/S 또는 부드러운 스트리밍 프로토콜을 사용하여 라이브 인코더에서 입력 스트림을 수신하고 하나 이상의 스트리밍 엔드포인트를 통해 스트리밍에 사용할 수 있도록 합니다. 또한 라이브 이벤트는 미리 보기 엔드포인트(미리 보기 URL)도 제공하며, 사용자는 이를 통해 추가적인 처리 및 전달 전에 스트림을 미리 보고 유효성을 검사할 수 있습니다.

이 자습서에서는 .NET 7.0을 사용하여 통과 라이브 이벤트를 만드는 방법을 보여줍니다. 통과 라이브 이벤트는 온-프레미스에서 다중 비트 전송률, GOP 정렬 인코딩을 수행할 수 있는 인코더가 있는 경우에 유용합니다. 클라우드 비용을 줄이는 방법이 될 수 있습니다. 대역폭을 줄이고 다중 비트 전송률 인코딩을 위해 단일 비트 전송률 스트림을 클라우드로 보내려면 720P 또는 1080P 인코딩 사전 설정과 함께 코드 변환 라이브 이벤트를 사용할 수 있습니다.

이 자습서에서는 다음을 수행합니다.

  • 샘플 프로젝트를 다운로드합니다.
  • 라이브 스트리밍을 수행하는 코드 검사
  • Media Player 데모 사이트에서 Azure Media Player로 이벤트 시청.
  • Event Grid를 설정하여 라이브 이벤트를 모니터링합니다.
  • 리소스를 정리합니다.

사전 요구 사항

이 자습서를 완료하려면 다음 항목이 필요합니다.

라이브 스트리밍 소프트웨어에도 다음 항목이 필요합니다.

  • 브로드캐스트 또는 이벤트에 사용되는 카메라 또는 디바이스(예: 랩톱).
  • 카메라 스트림을 인코딩하고 RTMP/S(Real-Time Messaging Protocol)를 통해 Media Services 라이브 스트리밍 서비스로 보내는 온-프레미스 소프트웨어 인코더입니다. 자세한 내용은 권장 온-프레미스 라이브 인코더를 참조하세요. 스트림은 RTMP/S 또는 부드러운 스트리밍 형식이어야 합니다. 이 샘플에서는 OBS(Open Broadcast Software) Studio를 사용하여 RTMP/S를 수집 엔드포인트로 브로드캐스트한다고 가정합니다. OBS Studio를 설치합니다.
  • 또는 OBS 빠른 시작을 시도하여 먼저 Azure Portal 전체 프로세스를 테스트할 수 있습니다.

Event Grid 및 Event Hubs를 사용하여 라이브 이벤트를 모니터링하려면 다음을 수행할 수 있습니다. 1. Azure Portal 또는 1을 사용하여 Event Grid를 사용하여 Media Services 이벤트 만들기 및 모니터링의 단계를 수행합니다. 이 문서의 Event Grid 및 Event Hubs를 사용하여 라이브 이벤트 모니터링 섹션에서 이 자습서의 끝 부분에 있는 단계를 따릅니다.

계속 진행하기 전에 Media Services v3를 통한 라이브 스트리밍을 검토하세요.

샘플 다운로드 및 구성

다음 명령을 사용하여 라이브 스트리밍 .NET 샘플이 포함된 GitHub 리포지토리를 머신에 복제합니다.

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

라이브 스트리밍 샘플은 Live/LiveEventWithDVR 폴더에 있습니다.

다운로드한 프로젝트에서 엽니다 appsettings.json . 값을 계정 이름, 구독 ID 및 리소스 그룹 이름으로 바꿉니다.

중요

이 샘플에서는 각 리소스에 고유한 접미사를 사용합니다. 디버깅을 취소하거나 앱을 실행하지 않고 종료하면 계정에서 여러 라이브 이벤트가 발생합니다. 실행 중인 라이브 이벤트를 중지해야 합니다. 그렇지 않으면 비용이 청구됩니다.

.NET SDK로 Media Services API 사용 시작

Program.cs 의 옵션을 appsettings.json사용하여 Media Services 계정 리소스에 대한 참조를 만듭니다.

var mediaServicesResourceId = MediaServicesAccountResource.CreateResourceIdentifier(
    subscriptionId: options.AZURE_SUBSCRIPTION_ID.ToString(),
    resourceGroupName: options.AZURE_RESOURCE_GROUP,
    accountName: options.AZURE_MEDIA_SERVICES_ACCOUNT_NAME);
var credential = new DefaultAzureCredential(includeInteractiveCredentials: true);
var armClient = new ArmClient(credential);
var mediaServicesAccount = armClient.GetMediaServicesAccountResource(mediaServicesResourceId);

라이브 이벤트 만들기

이 섹션에서는 통과 형식의 라이브 이벤트(LiveEventEncodingType이 없음으로 설정됨)를 만드는 방법을 보여 줍니다. 사용할 수 있는 유형에 대한 정보는 라이브 이벤트 유형을 참조하세요. 전체 수집 대역폭을 줄이려거나 온-프레미스 다중 비트 전송률 트랜스코더가 없는 경우 720p 또는 1080p 적응 비트 전송률 클라우드 인코딩에 라이브 트랜스코딩 이벤트를 사용할 수 있습니다.

라이브 이벤트를 만들 때 다음 항목을 지정할 수 있습니다.

  • 라이브 이벤트에 대한 수집 프로토콜. 현재 RTMPS 및 부드러운 스트리밍 프로토콜이 지원됩니다. 라이브 이벤트가 실행되는 동안에는 프로토콜 옵션을 변경할 수 없습니다. 다른 프로토콜이 필요한 경우 각 스트리밍 프로토콜에 대해 별도의 라이브 이벤트를 만듭니다.

  • 수집 및 미리 보기에 대한 IP 제한. 이 라이브 이벤트에 비디오를 수집하도록 허용된 IP 주소를 정의할 수 있습니다. 허용된 IP 주소는 다음 옵션 중 하나로 지정할 수 있습니다.

    • 단일 IP 주소(예: 10.0.0.1 또는 2001:db8::1)

    • IP 주소와 CIDR(Classless Inter-Domain Routing) 서브넷 마스크를 사용하는 IP 범위(예: 10.0.0.1/22 또는 2001:db8:::/48)

    • IP 주소와 점선 10진수 서브넷 마스크를 사용하는 IP 범위(예: 10.0.0.1 255.255.252.0)

      지정된 IP 주소가 없고 정의된 규칙이 없는 경우, IP 주소가 허용되지 않습니다. IP 주소를 허용하려면 규칙을 만들고 0.0.0.0/0 및 ::/0을 설정합니다. IP 주소는 4개의 숫자 또는 CIDR 주소 범위가 있는 IPv4 또는 IPv6 주소 형식 중 하나여야 합니다. 자세한 내용은 IP 허용 목록을 사용하여 DRM 라이선스 및 AES 키 배달에 대한 액세스 제한을 참조하세요.

  • 이벤트를 만들 때 자동으로 시작됩니다. 자동 시작을 true로 설정하면 라이브 이벤트는 만든 후에 시작됩니다. 즉, 라이브 이벤트를 실행하는 즉시 청구가 시작됩니다. 추가 청구를 중지하려면 라이브 이벤트 리소스에 대해 명시적으로 Stop을 호출해야 합니다. 자세한 내용은 라이브 이벤트 상태 및 청구를 참조하세요.

    대기 모드는 실행 상태로 더 빠르게 전환할 수 있게 만들어주는 저렴한 '할당됨' 상태에서 라이브 이벤트를 시작하는 데 사용됩니다. 스트리머에게 채널을 신속하게 나눠야 하는 핫 풀과 같은 상황에 유용합니다.

  • 정적 호스트 이름 및 고유 GUID. 수집 URL이 예측 가능하고 하드웨어 기반 라이브 인코더에서 유지 관리하기 쉽도록 속성을 true로 설정합니다 useStaticHostname . 자세한 내용은 라이브 이벤트 수집 URL을 참조하세요.

    var liveEvent = await mediaServicesAccount.GetMediaLiveEvents().CreateOrUpdateAsync(
        WaitUntil.Completed,
        liveEventName,
        new MediaLiveEventData(mediaServicesAccount.Get().Value.Data.Location)
        {
            Description = "Sample Live Event from the .NET SDK sample",
            UseStaticHostname = true,
            // 1) Set up the input settings for the Live event...
            Input = new LiveEventInput(streamingProtocol: LiveEventInputProtocol.Rtmp)
            {
                StreamingProtocol = LiveEventInputProtocol.Rtmp,
                AccessToken = "acf7b6ef-8a37-425f-b8fc-51c2d6a5a86a", // used to make the ingest URL unique
                KeyFrameIntervalDuration = TimeSpan.FromSeconds(2),
                IPAllowedIPs =
                {
                    new IPRange
                    {
                        Name = "AllowAllIpV4Addresses",
                        Address = IPAddress.Parse("0.0.0.0"),
                        SubnetPrefixLength = 0
                    },
                    new IPRange
                    {
                        Name = "AllowAllIpV6Addresses",
                        Address = IPAddress.Parse("0::"),
                        SubnetPrefixLength = 0
                    }
                }
            },
            // 2) Set the live event to use pass-through or cloud encoding modes...
            Encoding = new LiveEventEncoding()
            {
                EncodingType = LiveEventEncodingType.PassthroughBasic
            },
            // 3) Set up the Preview endpoint for monitoring
            Preview = new LiveEventPreview
            {
                IPAllowedIPs =
                {
                    new IPRange()
                    {
                        Name = "AllowAllIpV4Addresses",
                        Address = IPAddress.Parse("0.0.0.0"),
                        SubnetPrefixLength = 0
                    },
                    new IPRange()
                    {
                        Name = "AllowAllIpV6Addresses",
                        Address = IPAddress.Parse("0::"),
                        SubnetPrefixLength = 0
                    }
                }
            },
            // 4) Set up more advanced options on the live event. Low Latency is the most common one. Set
            //    this to Default or Low Latency. When using Low Latency mode, you must configure the Azure
            //    Media Player to use the quick start heuristic 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.
            StreamOptions =
            {
                StreamOptionsFlag.LowLatency
            },
            // 5) Optionally enable live transcriptions if desired. This is only supported on
            //    PassthroughStandard, and the transcoding live event types. It is not supported on Basic
            //    pass-through type.
            // WARNING: This is extra cost, so please check pricing before enabling.
            //Transcriptions =
            //{
            //    new LiveEventTranscription
            //    {
            //        // The value should be in BCP-47 format (e.g: 'en-US'). See https://go.microsoft.com/fwlink/?linkid=2133742
            //        Language = "en-us",
            //        TrackName = "English" // set the name you want to appear in the output manifest
            //    }
            //}
        },
        autoStart: false);
    

수집 URL 가져오기

라이브 이벤트가 생성되면 라이브 인코더에 제공할 수집 URL을 가져올 수 있습니다. 인코더는 이러한 URL을 사용하여 라이브 스트림을 입력합니다.

// Get the RTMP ingest URL. The endpoints is a collection of RTMP primary and secondary,
// and RTMPS primary and secondary URLs.
Console.WriteLine($"The RTMP ingest URL to enter into OBS Studio is:");
Console.WriteLine(liveEvent.Data.Input.Endpoints.First(x => x.Uri.Scheme == "rtmps").Uri);
Console.WriteLine("Make sure to enter a Stream Key into the OBS Studio settings. It can be");
Console.WriteLine("any value or you can repeat the accessToken used in the ingest URL path.");
Console.WriteLine();

미리 보기 URL 가져오기

previewEndpoint를 사용하여 인코더의 입력이 수신되고 있는지 미리 보고 확인합니다.

중요

계속하기 전에 비디오가 미리 보기 URL로 전달되고 있는지 확인합니다.

// Use the previewEndpoint to preview and verify that the input from the encoder is actually
// being received The preview endpoint URL also support the addition of various format strings
// for HLS (format=m3u8-cmaf) and DASH (format=mpd-time-cmaf) for example. The default manifest
// is Smooth.
string previewEndpoint = liveEvent.Data.Preview.Endpoints.First().Uri.ToString();
Console.WriteLine($"The preview URL is:");
Console.WriteLine(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($"https://ampdemo.azureedge.net/?url={HttpUtility.UrlEncode(previewEndpoint)}&heuristicprofile=lowlatency");
Console.WriteLine();
Console.WriteLine("Start the live stream now, sending the input to the ingest URL and verify");
Console.WriteLine("that it is arriving with the preview URL.");
Console.WriteLine("IMPORTANT: Make sure that the video is flowing to the Preview URL before continuing!");
Console.WriteLine("Press enter to continue...");
Console.ReadLine();

라이브 이벤트 및 라이브 출력 만들기 및 관리

온-프레미스 인코더의 라이브 스트림이 라이브 이벤트로 스트리밍되면 자산, 라이브 출력 및 스트리밍 로케이터를 만들어 라이브 이벤트를 시작할 수 있습니다. 스트림은 보관되며 스트리밍 엔드포인트를 통해 뷰어에서 사용할 수 있습니다.

다음 섹션에서는 자산 및 라이브 출력을 만드는 과정을 설명합니다.

자산 만들기

라이브 출력에서 사용할 자산을 만듭니다.

// Create an Asset for the Live Output to use. Think of this as the "tape" that will be recorded
// to. The asset entity points to a folder/container in your Azure Storage account
Console.Write($"Creating the output Asset '{assetName}'...".PadRight(60));
var asset = (await mediaServicesAccount.GetMediaAssets().CreateOrUpdateAsync(
    WaitUntil.Completed,
    assetName,
    new MediaAssetData
    {
        Description = "My video description"
    })).Value;
Console.WriteLine("Done");

라이브 출력 만들기

라이브 출력은 생성되면 시작되고 삭제되면 중지됩니다. 라이브 출력을 삭제하는 경우 자산의 출력 자산 또는 콘텐츠를 삭제하지 않습니다. 녹음이 포함된 자산은 존재하고 연결된 스트리밍 로케이터가 있는 한 주문형 스트리밍에 사용할 수 있습니다.

// Create the Live Output - think of this as the "tape recorder for the live event". Live
// outputs are optional, but are required if you want to archive the event to storage, use the
// asset for on-demand playback later, or if you want to enable cloud DVR time-shifting. We will
// use the asset created above for the "tape" to record to.
Console.Write($"Creating Live Output...".PadRight(60));
var liveOutput = (await liveEvent.GetMediaLiveOutputs().CreateOrUpdateAsync(
    WaitUntil.Completed,
    liveOutputName,
    new MediaLiveOutputData
    {
        AssetName = asset.Data.Name,
        // The HLS and DASH manifest file name. This is recommended to
        // set if you want a deterministic manifest path up front.
        // archive window can be set from 3 minutes to 25 hours.
        // Content that falls outside of ArchiveWindowLength is
        // continuously discarded from storage and is non-recoverable.
        // For a full event archive, set to the maximum, 25 hours.
        ManifestName = manifestName,
        ArchiveWindowLength = TimeSpan.FromHours(1)
    })).Value;
Console.WriteLine("Done");

스트리밍 로케이터 만들기

참고

Media Services 계정이 생성되면 기본 스트리밍 엔드포인트가 중지됨 상태로 계정에 추가됩니다. 콘텐츠 스트리밍을 시작하고 동적 패키징 및 동적 암호화를 활용하려면 콘텐츠를 스트리밍하려는 스트리밍 엔드포인트가 실행 상태에 있어야 합니다.

스트리밍 로케이터를 만들어 자산을 게시합니다. 라이브 이벤트(DVR 창 길이까지)는 스트리밍 로케이터의 만료 또는 삭제까지 볼 수 있으며, 그 중 가장 먼저 발생합니다. 시청 대상 그룹이 라이브 및 요청 시 비디오를 볼 수 있도록 하는 방법입니다. 라이브 이벤트가 완료되고 라이브 출력이 삭제될 때 동일한 URL을 사용하여 라이브 이벤트, DVR 창 또는 주문형 자산을 watch 수 있습니다.

var streamingLocator = (await mediaServicesAccount.GetStreamingLocators().CreateOrUpdateAsync(
    WaitUntil.Completed,
    streamingLocatorName,
    new StreamingLocatorData
    {
        AssetName = asset.Data.Name,
        StreamingPolicyName = "Predefined_ClearStreamingOnly",
        Filters =
        {
            filter.Data.Name
        }
    })).Value;

이벤트 보기

코드를 실행합니다. 출력 스트리밍 URL을 사용하여 라이브 이벤트를 watch. 스트리밍 로케이터 URL을 복사합니다. 원하는 미디어 플레이어를 사용할 수 있습니다. Media Player 데모 사이트를 사용하여 스트림을 테스트할 수 있습니다. URL 필드에 URL을 입력하고 플레이어 업데이트를 선택합니다.

Event Grid 및 Event Hubs를 사용하여 라이브 이벤트 모니터링

샘플 프로젝트는 Event Grid 및 Event Hubs를 사용하여 라이브 이벤트를 모니터링할 수 있습니다. 다음을 사용하여 Event Grid를 설정하고 사용할 수 있습니다.

모니터링을 사용하도록 설정하려면 다음을 수행합니다.

  1. Azure Portal 사용하여 Event Hubs 네임스페이스 및 Event Hubs 만들기
    1. Azure Portal 맨 위에 있는 텍스트 상자를 사용하여 "Event Hubs"를 검색합니다.
    2. 목록에서 Event Hub 를 선택한 다음 지침에 따라 Event Hubs 네임스페이스를 만듭니다.
    3. Event Hubs 네임스페이스 리소스로 이동합니다.
    4. 포털 메뉴의 엔터티 섹션에서 Event Hubs를 선택합니다.
    5. Event Hubs 네임스페이스에서 Event Hubs를 만듭니다.
    6. Event Hubs 리소스로 이동합니다.
    7. 액세스 제어, 추가, 역할 할당 추가를 차례로 선택합니다.
    8. Azure Event Hubs 데이터 수신기를 선택한 다음 자신에게 액세스 권한을 부여합니다.
    9. 액세스 제어, 추가, 역할 할당 추가를 차례로 선택합니다.
    10. Azure Event Hubs Data Sender를 선택한 다음 Media Services 계정에 대해 만든 관리 ID에 부여합니다.
  2. Azure Portal 사용하여 Azure Storage 계정을 만듭니다.
    1. 스토리지 계정을 만든 후 스토리지 계정 리소스로 이동합니다.
    2. 액세스 제어, 추가, 역할 할당 추가를 차례로 선택합니다.
    3. Storage Blob 데이터 기여자를 선택한 다음, 자신에게 이 액세스 권한을 부여합니다.
  3. 이벤트 구독 만들기
    1. Media Services 계정으로 이동합니다.
    2. 포털 메뉴에서 이벤트를 선택합니다.
    3. + 이벤트 구독을 선택합니다.
    4. 구독 이름 및 시스템 문서 이름을 입력합니다.
    5. 엔드포인트 유형을Event Hub설정합니다.
    6. Event Hubs를 이전에 만든 Event Hubs로 설정하고 관리 ID를 이전에 보낸 사람에게 Event Hubs에 대한 액세스 권한이 부여된 ID로 설정합니다.
  4. appsetttings.json 파일을 업데이트합니다.
    1. EVENT_HUB_NAMESPACE 네임스페이스의 전체 이름으로 설정합니다. 은(는) 과 myeventhub.servicebus.windows.net유사해야 합니다.
    2. EVENT_HUB_NAME 설정합니다.
    3. AZURE_STORAGE_ACCOUNT_NAME 설정합니다.

샘플을 다시 실행합니다. Event Hubs 통합을 사용하도록 설정하면 샘플은 인코더가 라이브 이벤트에 연결되고 연결이 끊어지면 이벤트를 기록합니다. 다른 다양한 이벤트도 기록됩니다.

샘플을 실행한 후 더 이상 필요하지 않은 경우 Event Hubs 및 스토리지 계정을 삭제합니다.

Media Services 계정의 리소스 정리

스트리밍 이벤트를 완료하고 이전에 프로비전된 리소스를 정리하려면 다음 절차를 따릅니다.

  1. 인코더에서 스트리밍을 중지합니다.
  2. 라이브 이벤트를 중지합니다. 라이브 이벤트가 중지된 후에는 요금이 발생하지 않습니다. 다시 시작해야 하는 경우 동일한 수집 URL을 사용할 수 있으므로 인코더를 다시 구성할 필요가 없습니다.
  3. 라이브 이벤트의 보관 파일을 주문형 스트림으로 계속 제공하지 않으려면 스트리밍 엔드포인트를 중지합니다. 라이브 이벤트가 중지됨 상태이면 요금이 발생하지 않습니다.
if (liveOutput != null)
{
    Console.Write("Deleting the Live Output...".PadRight(60));
    await liveOutput.DeleteAsync(WaitUntil.Completed);
    Console.WriteLine("Done");
}

if (liveEvent?.Data.ResourceState == LiveEventResourceState.Running)
{
    Console.Write("Stopping the Live Event...".PadRight(60));
    await liveEvent.StopAsync(WaitUntil.Completed, new LiveEventActionContent() { RemoveOutputsOnStop = true });
    Console.WriteLine("Done");
}

if (liveEvent != null)
{
    Console.Write("Deleting the Live Event...".PadRight(60));
    await liveEvent.DeleteAsync(WaitUntil.Completed);
    Console.WriteLine("Done");
}

if (streamingLocator != null)
{
    Console.Write("Deleting the Streaming Locator...".PadRight(60));
    await streamingLocator.DeleteAsync(WaitUntil.Completed);
    Console.WriteLine("Done");
}

if (asset != null)
{
    Console.Write("Deleting the Asset...".PadRight(60));
    await asset.DeleteAsync(WaitUntil.Completed);
    Console.WriteLine("Done");
}

나머지 리소스 정리

이 자습서에 대해 만든 Media Services 및 스토리지 계정이 더 이상 필요하지 않은 경우 이전에 만든 리소스 그룹을 삭제합니다.

다음 CLI 명령을 실행합니다.


az group delete --name amsResourceGroup

도움말 및 지원 보기

다음 방법 중 하나로 Media Services에 질문하거나 업데이트를 따를 수 있습니다.