미디어 플레이어

미디어 재생에는 인라인(페이지에 포함되거나 다른 컨트롤 그룹과 함께 포함) 또는 전용 전체 화면 환경을 통해 비디오와 오디오를 보고 듣는 것이 포함됩니다.

사용자는 재생/일시 중지, 뒤로 건너뛰기, 앞으로 건너뛰기와 같은 기본 컨트롤을 기대하며, 개발자는 이러한 기본 컨트롤(미디어 플레이어의 단추, 컨트롤 막대의 배경, 컨트롤 정렬 또는 레이아웃 포함)을 필요한 대로 수정할 수 있습니다.

A screenshot of a media player element with transport controls playing a video of a ladybug

올바른 컨트롤인가요?

앱에서 오디오 또는 비디오를 재생해야 할 때 미디어 플레이어를 사용합니다. 이미지 컬렉션을 표시하려면 대칭 이동 보기를 사용합니다.

권장 사항

미디어 플레이어는 밝은 테마와 어두운 테마를 모두 지원하지만 어두운 테마가 대부분의 엔터테인먼트 시나리오에서 더 나은 환경을 제공합니다. 어두운 배경은 특히 조명이 약한 조건에서 더욱 뛰어난 대비를 제공하며, 컨트롤 막대가 보기 환경을 방해하지 않도록 제한합니다.

비디오 콘텐츠를 재생할 때는 인라인 모드 위로 전체 화면 모드를 승격하여 전용 보기 환경을 권장합니다. 전체 화면 보기 환경이 최적이며, 인라인 모드에서는 옵션이 제한됩니다.

화면 부동산이 있는 경우 이중 행 레이아웃을 사용해 이동합니다. 소형 단일 행 레이아웃보다 컨트롤 공간을 더 많이 제공하며 다양한 입력을 사용하여 더욱 쉽게 탐색할 수 있습니다.

기본 컨트롤은 미디어 재생용으로 최적화되어 있지만, 앱에 최상의 환경을 제공할 수 있도록 미디어 플레이어에 필요한 사용자 지정 옵션을 추가할 수 있습니다. 사용자 지정 컨트롤을 추가하는 방법에 대한 자세한 내용은 사용자 지정 전송 컨트롤 만들기를 참조하세요.

UWP 및 WinUI 2

Important

이 문서의 정보 및 예제는 Windows 앱 SDKWinUI 3를 사용하는 앱에 최적화되어 있지만 일반적으로 WinUI 2를 사용하는 UWP 앱에 적용할 수 있습니다. 플랫폼별 정보 및 예제는 UWP API 참조를 확인하세요.

이 섹션에는 UWP 또는 WinUI 2 앱에서 컨트롤을 사용하는 데 필요한 정보가 있습니다.

이 컨트롤용 API는 Windows.UI.Xaml.Controls 네임스페이스에 있습니다.

최신 WinUI 2를 사용하여 모든 컨트롤에 대한 최신 스타일과 템플릿을 가져오는 것이 좋습니다. WinUI 2.2 이상에는 둥근 모서리를 사용하는 이 컨트롤의 새 템플릿이 포함되어 있습니다. 자세한 내용은 모서리 반경을 참조하세요.

10피트 환경을 디자인하는 경우 이중 행 레이아웃을 사용하여 이동합니다. 소형 단일 행 레이아웃보다 컨트롤 공간을 더 많이 제공하고 10피트 게임 패드를 사용하여 더욱 쉽게 탐색할 수 있습니다. 10피트 환경을 위한 애플리케이션 최적화에 대한 자세한 내용은 Xbox 및 TV용 디자인 문서를 참조하세요.

MediaPlayerElement는 Windows 10 버전 1607 이상에서만 사용할 수 있습니다. 이전 버전의 Windows 10 앱을 개발하는 경우 MediaElement 컨트롤을 대신 사용해야 합니다. 여기에 표시된 모든 권장 사항은 MediaElement에도 적용됩니다.

미디어 플레이어 만들기

WinUI 3 갤러리 앱에는 대부분의 WinUI 3 컨트롤, 특징, 기능의 대화형 예제가 포함되어 있습니다. Microsoft Store에서 앱을 다운로드하거나 GitHub에서 소스 코드를 가져오세요.

XAML에서 MediaPlayerElement 개체를 만들어 미디어를 앱에 추가하고 소스를 오디오 또는 비디오 파일을 가리키는 MediaSource로 설정합니다.

이 XAML은 MediaPlayerElement를 만들고 그 소스 속성을 앱에 로컬인 비디오 파일의 URI로 설정합니다. 페이지가 로드되면 MediaPlayerElement 재생이 시작됩니다. 미디어가 바로 시작되지 않게 하려면 AutoPlay 속성을 false로 설정하면 됩니다.

<MediaPlayerElement x:Name="mediaPlayerElement"
                    Source="ms-appx:///Videos/video1.mp4"
                    Width="400" AutoPlay="True"/>

이 XAML은 기본 제공 전송 컨트롤이 사용되고 AutoPlay 속성이 false.로 설정된 MediaPlayerElement를 만듭니다.

<MediaPlayerElement x:Name="mediaPlayerElement"
                    Source="ms-appx:///Videos/video1.mp4"
                    Width="400"
                    AutoPlay="False"
                    AreTransportControlsEnabled="True"/>

Important

MediaPlayerElement.Source를 상대 URI(ms-appx/ms-resource)로 설정하는 것은 Windows 애플리케이션 패키징 프로젝트로 패키지된 앱에서만 됩니다. 앱에서 Windows 애플리케이션 패키징 프로젝트를 사용하지 않는 경우에 권장되는 해결 방법은 상대 ms-appx:/// URI를 완전히 확인된 file:/// URI로 변환하는 것입니다. 이 문서의 뒷부분에 나오는 미디어 소스 설정로컬 미디어 파일 열기 섹션도 참조하세요.

미디어 전송 컨트롤

MediaPlayerElement는 재생, 중지, 일시 중지, 볼륨, 음소거, 검색/진행률, 선택 자막 및 오디오 트랙을 처리하는 전송 컨트롤을 기본적으로 제공합니다. 이러한 컨트롤을 사용하도록 설정하려면 AreTransportControlsEnabledtrue로 설정합니다. 사용하지 않도록 설정하려면 AreTransportControlsEnabledfalse로 설정합니다. 전송 컨트롤은 MediaTransportControls 클래스로 표현됩니다. 전송 컨트롤을 있는 그대로 사용하거나 다양한 방식으로 사용자 지정할 수 있습니다. 자세한 내용은 MediaTransportControls 클래스 참조 및 사용자 지정 전송 컨트롤 만들기를 참조하세요.

전송 컨트롤은 단일 행 및 이중 행 레이아웃을 지원합니다. 여기서 첫 번째 예는 미디어 타임라인 왼쪽에 재생/일시 중지 단추가 있는 단일 행 레이아웃입니다. 이 레이아웃은 인라인 미디어 재생 및 컴팩트 화면에 가장 적합합니다.

Example of MTC controls, single row

이중 행 컨트롤 레이아웃(아래)은 대부분의 사용 시나리오, 특히 큰 화면에 권장됩니다. 이 레이아웃은 컨트롤 공간이 더 많고 사용자가 타임라인 더 쉽게 작동할 수 있습니다.

Example of MTC controls, double row

시스템 미디어 전송 컨트롤

MediaPlayerElement는 시스템 미디어 전송 컨트롤과 자동으로 통합됩니다. 시스템 미디어 전송 컨트롤은 키보드의 미디어 단추 같은 하드웨어 미디어 키를 누를 때 팝업되는 컨트롤입니다. 자세한 내용은 SystemMediaTransportControls를 참조하세요.

미디어 소스 설정

네트워크 또는 앱에 포함된 파일에서 파일을 재생하려면 소스 속성을 파일 경로가 있는 MediaSource로 설정합니다.

인터넷에서 파일을 열려면 앱의 매니페스트(Package.appxmanifest)에서 인터넷(클라이언트) 기능을 선언해야 합니다. 기능 선언에 대한 자세한 내용은 앱 기능 선언을 참조하세요.

다음 코드는 XAML로 정의된 MediaPlayerElementSource 속성을 TextBox에 입력한 파일의 경로로 설정하려고 시도합니다.

<TextBox x:Name="txtFilePath" Width="400"
         FontSize="20"
         KeyUp="TxtFilePath_KeyUp"
         Header="File path"
         PlaceholderText="Enter file path"/>
private void TxtFilePath_KeyUp(object sender, KeyRoutedEventArgs e)
{
    if (e.Key == Windows.System.VirtualKey.Enter)
    {
        TextBox tbPath = sender as TextBox;

        if (tbPath != null)
        {
            LoadMediaFromString(tbPath.Text);
        }
    }
}

private void LoadMediaFromString(string path)
{
    try
    {
        Uri pathUri = new Uri(path);
        mediaPlayerElement.Source = MediaSource.CreateFromUri(pathUri);
    }
    catch (Exception ex)
    {
        if (ex is FormatException)
        {
            // handle exception.
            // For example: Log error or notify user problem with file
        }
    }
}

미디어 소스를 앱에 포함된 미디어 파일로 설정하려면 경로 앞에 ms-appx:///를 붙여 Uri를 초기화한 다음 이 Uri로 MediaSource를 만들고 소스를 Uri로 설정합니다. 예를 들어, 비디오 하위 폴더에 있는 video1.mp4라는 파일은 경로가 다음과 같습니다.ms-appx:///Videos/video1.mp4

Important

MediaPlayerElement.Source를 상대 URI(ms-appx/ms-resource)로 설정하는 것은 Windows 애플리케이션 패키징 프로젝트로 패키지된 앱에서만 됩니다.

이 코드는 이전에 XAML에서 정의한 MediaPlayerElement소스 속성을 ms-appx:///Videos/video1.mp4로 설정합니다.

private void LoadEmbeddedAppFile()
{
    try
    {
        Uri pathUri = new Uri("ms-appx:///Videos/video1.mp4");
        mediaPlayerElement.Source = MediaSource.CreateFromUri(pathUri);
    }
    catch (Exception ex)
    {
        if (ex is FormatException)
        {
            // handle exception.
            // For example: Log error or notify user problem with file
        }
    }
}

로컬 미디어 파일 열기

로컬 시스템 또는 OneDrive에서 파일을 열려면 FileOpenPicker를 사용하여 파일 및 소스를 가져와 미디어 소스를 설정하거나 프로그래밍 방식으로 사용자 미디어 폴더에 액세스할 수 있습니다.

음악 또는 비디오 폴더에 대한 사용자 상호 작용 없이 앱에 액세스해야 하는 경우(예: 사용자의 컬렉션에 있는 모든 음악 또는 비디오 파일을 열거하고 앱에 표시하는 경우) 음악 라이브러리비디오 라이브러리 기능을 선언해야 합니다. 자세한 내용은 음악, 사진 및 동영상 라이브러리의 파일 및 폴더를 참조하세요.

사용자가 어떤 파일에 액세스할지 완전히 제어하므로 FileOpenPicker에는 사용자의 음악 또는 동영상 폴더 등 로컬 파일 시스템에 있는 파일에 액세스하기 위해 특별한 접근 권한 값이 필요하지 않습니다. 보안 및 개인정보 보호의 측면에서는 앱이 사용하는 기능 수를 최소화하는 것이 가장 좋습니다.

FileOpenPicker를 사용하여 로컬 미디어를 열려면

  1. FileOpenPicker를 호출하여 사용자가 미디어 파일을 선택할 수 있게 합니다.

    FileOpenPicker 클래스를 사용하여 미디어 파일을 선택합니다. FileTypeFilter를 설정하여 FileOpenPicker가 표시하는 파일 형식을 지정합니다. PickSingleFileAsync를 호출하여 파일 선택기를 시작하고 파일을 가져옵니다.

  2. MediaSource를 사용하여 선택한 미디어 파일을 MediaPlayerElement.Source로 설정합니다.

    FileOpenPicker에서 반환된 StorageFile을 사용하려면 MediaSource에서 CreateFromStorageFile 메서드를 호출하고 이를 MediaPlayerElement소스로 설정해야 합니다. 그런 다음 MediaPlayerElement.MediaPlayer에서 Play를 호출하여 미디어를 시작합니다.

이 예제는 FileOpenPicker를 사용하여 파일을 선택하고 MediaPlayerElementSource로 설정하는 방법을 보여 줍니다.

<MediaPlayerElement x:Name="mediaPlayerElement"/>
...
<Button Content="Choose file" Click="Button_Click"/>
private async void Button_Click(object sender, RoutedEventArgs e)
{
    await SetLocalMedia();
}

async private System.Threading.Tasks.Task SetLocalMedia()
{
    var openPicker = new Windows.Storage.Pickers.FileOpenPicker();
    WinRT.Interop.InitializeWithWindow.Initialize(openPicker, WinRT.Interop.WindowNative.GetWindowHandle(this));

    openPicker.FileTypeFilter.Add(".wmv");
    openPicker.FileTypeFilter.Add(".mp4");
    openPicker.FileTypeFilter.Add(".wma");
    openPicker.FileTypeFilter.Add(".mp3");

    var file = await openPicker.PickSingleFileAsync();

    // mediaPlayerElement is a MediaPlayerElement control defined in XAML
    if (file != null)
    {
        mediaPlayerElement.Source = MediaSource.CreateFromStorageFile(file);

        mediaPlayerElement.MediaPlayer.Play();
    }
}

포스터 소스 설정

PosterSource 속성을 사용하여 미디어 로드 전에 MediaPlayerElement에 시각적 표현을 제공할 수 있습니다. PosterSource는 미디어 대신 표시되는 스크린샷, 영화 포스터 또는 앨범 아트 같은 이미지입니다. 다음과 같은 경우에는 PosterSource가 표시됩니다.

  • 유효한 소스가 설정되지 않은 경우 예를 들어, 소스가 설정되지 않았거나, Sourcenull로 설정되어 있거나, 소스가 잘못된 경우(예: MediaFailed 이벤트가 발생한 경우)가 있습니다.
  • 미디어가 로드되는 동안. 예를 들어, 유효한 소스가 설정되어 있지만 MediaOpened 이벤트가 아직 발생하지 않았습니다.
  • 미디어가 또 다른 디바이스로 스트리밍되는 경우.
  • 미디어가 오디오 전용인 경우.

다음은 해당 Source가 앨범 트랙으로 설정되고 해당 PosterSource가 앨범 커버의 이미지로 설정된 MediaPlayerElement입니다.

<MediaPlayerElement Source="ms-appx:///Media/Track1.mp4" PosterSource="ms-appx:///Media/AlbumCover.png"/>

디바이스 화면을 활성 상태로 유지

일반적으로 디바이스는 사용자가 자리를 비우면 디스플레이를 흐리게 하고(결국 꺼지게 하여) 배터리 수명을 절약하지만 비디오 앱은 사용자가 비디오를 볼 수 있도록 화면이 켜져 있게 해야 합니다. 앱이 동영상을 재생 중일 때와 같이 사용자 작업이 더 이상 감지되지 않을 때 디스플레이가 비활성화되지 않게 하려면 DisplayRequest.RequestActive를 호출하면 됩니다. DisplayRequest 클래스를 사용하면 사용자가 비디오를 볼 수 있도록 Windows에게 디스플레이를 계속 켜두라고 지시할 수 있습니다.

전원 및 배터리 사용 시간을 절약하려면 DisplayRequest.RequestRelease를 호출하여 더 이상 필요하지 않을 때 디스플레이 요청을 해제해야 합니다. Windows는 앱이 화면에서 벗어날 때 앱의 활성 디스플레이 요청을 자동으로 비활성화하고 앱이 다시 제일 앞으로 오면 다시 활성화합니다.

다음은 디스플레이 요청을 해제해야 하는 몇 가지 상황입니다.

  • 예를 들어, 비디오 재생은 사용자 작업, 버퍼링 또는 제한된 대역폭으로 인한 조정으로 인해 일시 중지됩니다.
  • 재생이 중지되었습니다. 예를 들어 비디오 재생이 완료되거나 프레젠테이션이 끝난 경우입니다.
  • 재생 오류가 발생했습니다. 예를 들어 네트워크 연결 문제 또는 손상된 파일의 경우입니다.

화면을 활성 상태로 유지하려면

  1. 전역 DisplayRequest 변수를 만듭니다. 이를 null로 초기화합니다.

    private DisplayRequest appDisplayRequest = null;
    
  2. RequestActive를 호출하여 앱이 디스플레이를 계속 켜야 한다고 Windows에 알립니다

  3. 재생 오류로 인해 비디오 재생이 중지, 일시 중지 또는 중단될 때마다 RequestRelease를 호출하여 디스플레이 요청을 해제합니다. 앱에 활성 디스플레이 요청이 더 이상 없으면 Windows는 디바이스가 사용되지 않을 때 디스플레이를 흐리게 하고 결국 꺼서 배터리 수명을 절약합니다.

MediaPlayerElement.MediaPlayer에는 PlaybackRate, PlaybackStatePosition 등 미디어 재생의 다양한 면을 제어하는 MediaPlaybackSession 형식의 PlaybackSession이 있습니다. 여기서는 MediaPlayer.PlaybackSession에서 PlaybackStateChanged 이벤트를 사용하여 디스플레이 요청을 해제해야 하는 상황을 감지합니다. 그런 다음 NaturalVideoHeight 속성을 사용하여 오디오 또는 비디오 파일의 재생 여부를 확인하고 비디오가 재생 중인 경우에만 화면을 활성 상태로 유지합니다.

<MediaPlayerElement x:Name="mediaPlayerElement" Source="ms-appx:///Videos/video1.mp4"/>
public sealed partial class MainWindow : Window
{
    public DisplayRequest appDisplayRequest = null;
    // using Microsoft.UI.Dispatching;
    private DispatcherQueue dispatcherQueue = DispatcherQueue.GetForCurrentThread();

    public MainWindow()
    {
        this.InitializeComponent();
        mediaPlayerElement.MediaPlayer.PlaybackSession.PlaybackStateChanged += 
            PlaybackSession_PlaybackStateChanged;
    }

    private void PlaybackSession_PlaybackStateChanged(MediaPlaybackSession sender, object args)
    {
        MediaPlaybackSession playbackSession = sender as MediaPlaybackSession;
        if (playbackSession != null && playbackSession.NaturalVideoHeight != 0)
        {
            if (playbackSession.PlaybackState == MediaPlaybackState.Playing)
            {
                if (appDisplayRequest is null)
                {
                    dispatcherQueue.TryEnqueue(DispatcherQueuePriority.Normal, () =>
                    {
                        appDisplayRequest = new DisplayRequest();
                        appDisplayRequest.RequestActive();
                    });
                }
            }
            else // PlaybackState is Buffering, None, Opening, or Paused.
            {
                if (appDisplayRequest is not null)
                {
                    appDisplayRequest.RequestRelease();
                    appDisplayRequest = null;
                }
            }
        }
    }
}

미디어 플레이어를 프로그래밍 방식으로 제어

MediaPlayerElementMediaPlayerElement.MediaPlayer 속성을 통해 오디오 및 비디오 재생을 제어하기 위한 다양한 속성, 메서드 및 이벤트를 제공합니다. 속성, 메서드 및 이벤트 전체 목록은 MediaPlayer 참조 페이지를 참조하세요.

고급 미디어 재생 시나리오

재생 목록 재생, 오디오 언어 간 전환 또는 사용자 지정 메타데이터 트랙 만들기와 같은 더 복잡한 미디어 재생 시나리오의 경우 MediaPlayerElement.SourceMediaPlaybackItem 또는 MediaPlaybackList로 설정합니다. 다양한 고급 미디어 기능 사용 방법은 미디어 재생 페이지를 참조하세요.

비디오 크기 조정 및 스트레치

스트레치 속성을 사용하여 비디오 콘텐츠 및/또는 PosterSource가 컨테이너를 채우는 방법을 변경합니다. 이렇게 하면 스트레치 값에 따라 비디오의 크기가 조정되고 확장됩니다. Stretch 상태는 대부분의 TV 세트의 사진 크기 설정과 유사합니다. 이를 단추에 연결하고 사용자가 원하는 설정을 선택할 수 있게 합니다.

  • None은 콘텐츠의 기본 해상도는 원래 크기로 표시되지 않습니다. 이로 인해 일부 비디오가 비디오 가장자리에서 잘리거나 검은색 막대가 될 수 있습니다.
  • Uniform은 가로 세로 비율과 비디오 콘텐츠를 유지하면서 최대한 많은 공간을 균일하게 채웁니다. 이로 인해 비디오 가장자리에 검은색 가로 또는 세로 막대가 표시될 수 있습니다. 이는 와이드 스크린 모드와 유사합니다.
  • UniformToFill은 가로 세로 비율을 유지하면서 전체 공간을 채웁니다. 이로 인해 비디오 일부가 잘릴 수 있습니다. 이는 전체 화면 모드와 유사합니다.
  • Fill은 전체 공간을 채우지만 가로 세로 비율을 유지하지는 않습니다. 비디오가 잘리지 않지만 스트레칭이 발생할 수 있습니다. 이는 스트레치 모드와 유사합니다.

Stretch enumeration values

여기서 AppBarButton스트레치 옵션을 순환하는 데 사용됩니다. switch 문은 스트레치 속성의 현재 상태를 확인하고 Stretch 열거형에서 그 다음 값으로 설정합니다. 이렇게 하면 사용자가 다른 스트레치 상태를 순환할 수 있습니다.

<AppBarButton Icon="Trim"
              Label="Resize Video"
              Click="PictureSize_Click" />
private void PictureSize_Click(object sender, RoutedEventArgs e)
{
    switch (mediaPlayerElement.Stretch)
    {
        case Stretch.Fill:
            mediaPlayerElement.Stretch = Stretch.None;
            break;
        case Stretch.None:
            mediaPlayerElement.Stretch = Stretch.Uniform;
            break;
        case Stretch.Uniform:
            mediaPlayerElement.Stretch = Stretch.UniformToFill;
            break;
        case Stretch.UniformToFill:
            mediaPlayerElement.Stretch = Stretch.Fill;
            break;
        default:
            break;
    }
}

짧은 대기 시간 재생 사용

RealTimePlayback 속성을 MediaPlayerElement.MediaPlayer에서 true로 설정하면 미디어 플레이어 요소의 재생에 대한 초기 대기 시간을 줄일 수 있습니다. 이는 양방향 통신 앱에 중요하며 일부 게임 시나리오에 적용할 수 있습니다. 이 모드는 리소스 집약적이라 전력 효율이 떨어집니다.

이 예제에서는 MediaPlayerElement를 만들고 RealTimePlaybacktrue로 설정합니다.

MediaPlayerElement mediaPlayerElement = new MediaPlayerElement();
mediaPlayerElement.MediaPlayer.RealTimePlayback = true;