백그라운드에서 미디어 파일 처리Process media files in the background

이 문서에서는 MediaProcessingTrigger 및 백그라운드 작업을 사용 하 여 백그라운드에서 미디어 파일을 처리 하는 방법을 보여 줍니다.This article shows you how to use the MediaProcessingTrigger and a background task to process media files in the background.

이 문서에서 설명 하는 예제 앱을 사용 하면 사용자는 트랜스 코딩을 위해 입력 미디어 파일을 선택 하 고 코드 변환 결과에 대 한 출력 파일을 지정할 수 있습니다.The example app described in this article allows the user to select an input media file to transcode and specify an output file for the transcoding result. 그런 다음, 코드 변환 작업을 수행 하기 위해 백그라운드 작업이 시작 됩니다.Then, a background task is launched to perform the transcoding operation. MediaProcessingTrigger 는 디스크에 미디어 컴포지션을 렌더링 하 고 처리가 완료 된 후 처리 된 미디어 파일을 업로드 하는 등 트랜스 코딩 외에 다양 한 미디어 처리 시나리오를 지원 하기 위한 것입니다.The MediaProcessingTrigger is intended to support many different media processing scenarios besides transcoding, including rendering media compositions to disk and uploading processed media files after processing is complete.

이 샘플에서 사용 되는 다양 한 유니버설 Windows 앱 기능에 대 한 자세한 내용은 다음을 참조 하세요.For more detailed information on the different Universal Windows app features utilized in this sample, see:

미디어 처리 백그라운드 작업 만들기Create a media processing background task

Microsoft Visual Studio에서 기존 솔루션에 백그라운드 작업을 추가 하려면 사용자의 구성 요소에 대 한 이름을 입력 합니다.To add a background task to your existing solution in Microsoft Visual Studio, Enter a name for your comp

  1. 파일 메뉴에서 추가 를 선택한 다음 새 프로젝트...를 선택 합니다.From the File menu, select Add and then New Project....
  2. 프로젝트 형식 Windows 런타임 구성 요소 (유니버설 Windows) 를 선택 합니다.Select the project type Windows Runtime Component (Universal Windows).
  3. 새 구성 요소 프로젝트의 이름을 입력 합니다.Enter a name for your new component project. 이 예제에서는 프로젝트 이름 MediaProcessingBackgroundTask을 사용 합니다.This example uses the project name MediaProcessingBackgroundTask.
  4. 확인을 클릭합니다.Click OK.

솔루션 탐색기에서 기본적으로 생성 되는 "Class1.cs" 파일의 아이콘을 마우스 오른쪽 단추로 클릭 하 고 이름 바꾸기를 선택 합니다.In Solution Explorer, right-click the icon for the "Class1.cs" file that is created by default and select Rename. 파일 이름을 "MediaProcessingTask.cs"로 바꿉니다.Rename the file to "MediaProcessingTask.cs". Visual Studio가이 클래스에 대 한 모든 참조의 이름을 바꿀지 묻는 메시지를 표시 하는 경우 를 클릭 합니다.When Visual Studio asks if you want to rename all of the references to this class, click Yes.

이름이 바뀐 클래스 파일에서 다음 using 지시문을 추가 하 여이 네임 스페이스를 프로젝트에 포함 합니다.In the renamed class file, add the following using directives to include these namespaces in your project.

using Windows.ApplicationModel.Background;
using Windows.Storage;
using Windows.UI.Notifications;
using Windows.Data.Xml.Dom;
using Windows.Media.MediaProperties;
using Windows.Media.Transcoding;
using System.Threading;

클래스가 IBackgroundTask에서 상속 하도록 클래스 선언을 업데이트 합니다.Update your class declaration to make your class inherit from IBackgroundTask.

public sealed class MediaProcessingTask : IBackgroundTask
{

클래스에 다음 멤버 변수를 추가 합니다.Add the following member variables to your class:

  • 백그라운드 작업의 진행 상태를 사용 하 여 포그라운드 앱을 업데이트 하는 데 사용할 IBackgroundTaskInstance 입니다.An IBackgroundTaskInstance that will be used to update the foreground app with the progress of the background task.
  • 미디어 트랜스 코딩을 비동기식으로 수행 하는 동안 시스템에서 백그라운드 작업을 종료 하는 것을 유지 하는 BackgroundTaskDeferral 입니다.A BackgroundTaskDeferral that keeps the system from shutting down your background task while media transcoding is being performed asynchronously.
  • 비동기 코드 변환 작업을 취소 하는 데 사용할 수 있는 CancellationTokenSource 개체입니다.A CancellationTokenSource object that can be used to cancel the asynchronous transcoding operation.
  • 미디어 파일을 트랜스 코딩 하는 데 사용 되는 MediaTranscoder 개체입니다.The MediaTranscoder object that will be used to transcode media files.
IBackgroundTaskInstance backgroundTaskInstance;
BackgroundTaskDeferral deferral;
CancellationTokenSource cancelTokenSource = new CancellationTokenSource();
MediaTranscoder transcoder;

작업을 시작할 때 시스템에서 백그라운드 작업의 Run 메서드를 호출 합니다.The system calls Run method of a background task when the task is launched. 메서드에 전달 된 IBackgroundTask 개체를 해당 멤버 변수로 설정 합니다.Set the IBackgroundTask object passed into the method to the corresponding member variable. 시스템이 백그라운드 작업을 종료 해야 하는 경우 발생 하는 취소 된 이벤트에 대 한 처리기를 등록 합니다.Register a handler for the Canceled event, which will be raised if the system needs to shut down the background task. 그런 다음 Progress 속성을 0으로 설정 합니다.Then, set the Progress property to zero.

그런 다음 백그라운드 작업 개체의 GetDeferral 메서드를 호출 하 여 지연을 가져옵니다.Next, call the background task object's GetDeferral method to obtain a deferral. 이렇게 하면 비동기 작업을 수행 하기 때문에 작업을 종료 하지 않도록 시스템에 지시할 수 있습니다.This tells the system not to shut down your task because you are performing asynchronous operations.

다음으로 다음 섹션에 정의 된 TranscodeFileAsync도우미 메서드를 호출 합니다.Next, call the helper method TranscodeFileAsync, which is defined in the next section. 성공적으로 완료 되 면 코드 변환이 완료 되었음을 사용자에 게 알리는 알림 메시지를 시작 하기 위해 도우미 메서드가 호출 됩니다.If that completes successfully, a helper method is called to launch a toast notification to alert the user that transcoding is complete.

Run 메서드가 끝날 때 지연 개체에서 complete 를 호출 하 여 백그라운드 작업이 완료 되 고 종료 될 수 있음을 시스템에 알립니다.At the end of the Run method, call Complete on the deferral object to let the system know that your background task is complete and can be terminated.

public async void Run(IBackgroundTaskInstance taskInstance)
{
    Debug.WriteLine("In background task Run method");

    backgroundTaskInstance = taskInstance;
    taskInstance.Canceled += new BackgroundTaskCanceledEventHandler(OnCanceled);
    taskInstance.Progress = 0;

    deferral = taskInstance.GetDeferral();
    Debug.WriteLine("Background " + taskInstance.Task.Name + " is called @ " + (DateTime.Now).ToString());

    try
    {
        await TranscodeFileAsync();
        ApplicationData.Current.LocalSettings.Values["TranscodingStatus"] = "Completed Successfully";
        SendToastNotification("File transcoding complete.");

    }
    catch (Exception e)
    {
        Debug.WriteLine("Exception type: {0}", e.ToString());
        ApplicationData.Current.LocalSettings.Values["TranscodingStatus"] = "Error ocurred: " + e.ToString();
    }


    deferral.Complete();
}

TranscodeFileAsync helper 메서드에서, 코드 변환 작업의 입력 및 출력 파일에 대 한 파일 이름은 앱에 대 한 LocalSettings 에서 검색 됩니다.In the TranscodeFileAsync helper method, the file names for the input and output files for the transcoding operations are retrieved from the LocalSettings for your app. 이러한 값은 포그라운드 앱에 의해 설정 됩니다.These values will be set by your foreground app. 입력 및 출력 파일에 대 한 StorageFile 개체를 만든 다음 트랜스 코딩에 사용할 인코딩 프로필을 만듭니다.Create a StorageFile object for the input and output files and then create an encoding profile to use for transcoding.

PrepareFileTranscodeAsync를 호출 하 고 입력 파일, 출력 파일 및 인코딩 프로필을 전달 합니다.Call PrepareFileTranscodeAsync, passing in the input file, output file, and encoding profile. 이 호출에서 반환 된 PrepareTranscodeResult 개체를 사용 하면 코드 변환을 수행할 수 있는지 알 수 있습니다.The PrepareTranscodeResult object returned from this call lets you know if transcoding can be performed. Cantranscode 코딩 속성이 True 이면 TranscodeAsync 를 호출 하 여 코드 변환 작업을 수행 합니다.If the CanTranscode property is true, call TranscodeAsync to perform the transcoding operation.

Ask ask 메서드를 사용 하 여 비동기 작업의 진행률을 추적 하거나 취소할 수 있습니다.The AsTask method enables you to track the progress the asynchronous operation or cancel it. 원하는 진행률 단위와 작업의 현재 진행 상태를 알리기 위해 호출 되는 메서드 이름을 지정 하 여 새 진행률 개체를 만듭니다.Create a new Progress object, specifying the units of progress you desire and the name of the method that will be called to notify you of the current progress of the task. 작업을 취소할 수 있도록 하는 취소 토큰과 함께 진행률 개체를 표시 합니다.Pass the Progress object into the AsTask method along with the cancellation token that allows you to cancel the task.

  private async Task TranscodeFileAsync()
  {
      transcoder = new MediaTranscoder();

      try
      {
          var settings = ApplicationData.Current.LocalSettings;

          settings.Values["TranscodingStatus"] = "Started";

          var inputFileName = ApplicationData.Current.LocalSettings.Values["InputFileName"] as string;
          var outputFileName = ApplicationData.Current.LocalSettings.Values["OutputFileName"] as string;

          if (inputFileName == null || outputFileName == null)
          {
              return;
          }


          // retrieve the transcoding information
          var inputFile = await Windows.Storage.StorageFile.GetFileFromPathAsync(inputFileName);
          var outputFile = await Windows.Storage.StorageFile.GetFileFromPathAsync(outputFileName);

          // create video encoding profile                
          MediaEncodingProfile encodingProfile = MediaEncodingProfile.CreateMp4(VideoEncodingQuality.HD720p);

          Debug.WriteLine("PrepareFileTranscodeAsync");
          settings.Values["TranscodingStatus"] = "Preparing to transcode ";
          PrepareTranscodeResult preparedTranscodeResult = await transcoder.PrepareFileTranscodeAsync(
              inputFile, 
              outputFile, 
              encodingProfile);

          if (preparedTranscodeResult.CanTranscode)
          {
              var startTime = TimeSpan.FromMilliseconds(DateTime.Now.Millisecond);
              Debug.WriteLine("Starting transcoding @" + startTime);

              var progress = new Progress<double>(TranscodeProgress);
              settings.Values["TranscodingStatus"] = "Transcoding ";
              settings.Values["ProcessingFileName"] = inputFileName;
              await preparedTranscodeResult.TranscodeAsync().AsTask(cancelTokenSource.Token, progress);

          }
          else
          {
              Debug.WriteLine("Source content could not be transcoded.");
              Debug.WriteLine("Transcode status: " + preparedTranscodeResult.FailureReason.ToString());
              var endTime = TimeSpan.FromMilliseconds(DateTime.Now.Millisecond);
              Debug.WriteLine("End time = " + endTime);
          }
      }
      catch (Exception e)
      {
          Debug.WriteLine("Exception type: {0}", e.ToString());
          throw;
      }
  }

이전 단계에서 progress 개체를 만드는 데 사용한 방법의 진행률에서 백그라운드 작업 인스턴스의 진행률을 설정합니다.In the method you used to create the Progress object in the previous step, Progress, set the progress of the background task instance. 이렇게 하면 실행 중인 포그라운드 앱에 진행률이 전달 됩니다.This will pass the progress to the foreground app, if it is running.

void TranscodeProgress(double percent)
{
    Debug.WriteLine("Transcoding progress:  " + percent.ToString().Split('.')[0] + "%");
    backgroundTaskInstance.Progress = (uint)percent;
}

Sendto notification 도우미 메서드는 텍스트 콘텐츠만 있는 알림 메시지에 대 한 템플릿 XML 문서를 가져와 새 알림 메시지를 만듭니다.The SendToastNotification helper method creates a new toast notification by getting a template XML document for a toast that only has text content. Toast XML의 text 요소가 설정 된 다음 XML 문서에서 새 To notification 개체가 만들어집니다.The text element of the toast XML is set and then a new ToastNotification object is created from the XML document. 마지막으로, 알림은 사용자에 게 표시 됩니다. 표시를 호출 합니다.Finally, the toast is shown to the user by calling ToastNotifier.Show.

private void SendToastNotification(string toastMessage)
{
    ToastTemplateType toastTemplate = ToastTemplateType.ToastText01;
    XmlDocument toastXml = ToastNotificationManager.GetTemplateContent(toastTemplate);

    //Supply text content for your notification
    XmlNodeList toastTextElements = toastXml.GetElementsByTagName("text");
    toastTextElements[0].AppendChild(toastXml.CreateTextNode(toastMessage));

    //Create the toast notification based on the XML content you've specified.
    ToastNotification toast = new ToastNotification(toastXml);

    //Send your toast notification.
    ToastNotificationManager.CreateToastNotifier().Show(toast);
}

시스템에서 백그라운드 작업을 취소할 때 호출 되는 취소 된 이벤트에 대 한 처리기에서 원격 분석을 위해 오류를 기록할 수 있습니다.In the handler for the Canceled event, which is called when the system cancels your background task, you can log the error for telemetry purposes.

private void OnCanceled(IBackgroundTaskInstance sender, BackgroundTaskCancellationReason reason)
{
    Debug.WriteLine("Background " + sender.Task.Name + " Cancel Requested..." + reason.ToString());
}

백그라운드 작업 등록 및 시작Register and launch the background task

포그라운드 앱에서 백그라운드 작업을 시작 하려면 먼저 응용 프로그램에서 백그라운드 작업을 사용 하 고 있음을 시스템에서 알 수 있도록 포그라운드 앱의 appmanifest 파일을 업데이트 해야 합니다.Before you can launch the background task from your foreground app, you must update your foreground app's Package.appmanifest file to let the system know that your app uses a background task.

  1. 솔루션 탐색기에서 appmanifest 파일 아이콘을 두 번 클릭 하 여 매니페스트 편집기를 엽니다.In Solution Explorer, double-click the Package.appmanifest file icon to open the manifest editor.
  2. 선언 탭을 선택 합니다.Select the Declarations tab.
  3. 사용 가능한 선언에서 백그라운드 작업 을 선택 하 고 추가를 클릭 합니다.From Available Declarations, select Background Tasks and click Add.
  4. 지원 되는 선언 에서 백그라운드 작업 항목이 선택 되어 있는지 확인 합니다.Under Supported Declarations make sure that the Background Tasks item is selected. 속성에서 미디어 처리확인란을 선택 합니다.Under Properties, select the checkbox for Media processing.
  5. 진입점 텍스트 상자에서 백그라운드 테스트에 대 한 네임 스페이스 및 클래스 이름을 마침표로 구분 하 여 지정 합니다.In the Entry Point text box, specify the namespace and class name for your background test, separated by a period. 이 예의 경우 항목은 다음과 같습니다.For this example, the entry is:
MediaProcessingBackgroundTask.MediaProcessingTask

다음으로 백그라운드 작업에 대 한 참조를 전경 앱에 추가 해야 합니다.Next, you need to add a reference to your background task to your foreground app.

  1. 솔루션 탐색기의 포그라운드 앱 프로젝트에서 참조 폴더를 마우스 오른쪽 단추로 클릭 하 고 참조 추가...를 선택 합니다.In Solution Explorer, under your foreground app project, right-click the References folder and select Add Reference....
  2. 프로젝트 노드를 확장 하 고 솔루션을 선택 합니다.Expand the Projects node and select Solution.
  3. 백그라운드 작업 프로젝트 옆의 확인란을 선택 하 고 확인을 클릭 합니다.Check the box next to your background task project and click OK.

이 예제의 나머지 코드는 전경 앱에 추가 해야 합니다.The rest of the code in this example should be added to your foreground app. 먼저 프로젝트에 다음 네임 스페이스를 추가 해야 합니다.First, you will need to add the following namespaces to your project.

using Windows.ApplicationModel.Background;
using Windows.Storage;

그런 다음 백그라운드 작업을 등록 하는 데 필요한 다음 멤버 변수를 추가 합니다.Next, add the following member variables that are needed to register the background task.

MediaProcessingTrigger mediaProcessingTrigger;
string backgroundTaskBuilderName = "TranscodingBackgroundTask";
BackgroundTaskRegistration taskRegistration;

PickFilesToTranscode 도우미 메서드는 fileopenpickerFileSavePicker 를 사용 하 여 트랜스 코딩을 위한 입력 및 출력 파일을 엽니다.The PickFilesToTranscode helper method uses a FileOpenPicker and a FileSavePicker to open the input and output files for transcoding. 사용자가 앱에 액세스할 수 없는 위치에서 파일을 선택할 수 있습니다.The user may select files in a location that your app does not have access to. 백그라운드 작업이 파일을 열 수 있도록 하려면 앱에 대 한 FutureAccessList 에 추가 합니다.To make sure your background task can open the files, add them to the FutureAccessList for your app.

마지막으로 앱에 대 한 LocalSettings 의 입력 및 출력 파일 이름에 대 한 항목을 설정 합니다.Finally, set entries for the input and output file names in the LocalSettings for your app. 백그라운드 작업은이 위치에서 파일 이름을 검색 합니다.The background task retrieves the file names from this location.

private async void PickFilesToTranscode()
{
    var openPicker = new Windows.Storage.Pickers.FileOpenPicker();

    openPicker.SuggestedStartLocation = Windows.Storage.Pickers.PickerLocationId.VideosLibrary;
    openPicker.FileTypeFilter.Add(".wmv");
    openPicker.FileTypeFilter.Add(".mp4");

    StorageFile source = await openPicker.PickSingleFileAsync();

    var savePicker = new Windows.Storage.Pickers.FileSavePicker();

    savePicker.SuggestedStartLocation =
        Windows.Storage.Pickers.PickerLocationId.VideosLibrary;

    savePicker.DefaultFileExtension = ".mp4";
    savePicker.SuggestedFileName = "New Video";

    savePicker.FileTypeChoices.Add("MPEG4", new string[] { ".mp4" });

    StorageFile destination = await savePicker.PickSaveFileAsync();

    if(source == null || destination == null)
    {
        return;
    }

    var storageItemAccessList = Windows.Storage.AccessCache.StorageApplicationPermissions.FutureAccessList;
    storageItemAccessList.Add(source);
    storageItemAccessList.Add(destination);

    ApplicationData.Current.LocalSettings.Values["InputFileName"] = source.Path;
    ApplicationData.Current.LocalSettings.Values["OutputFileName"] = destination.Path;
}

백그라운드 작업을 등록 하려면 새 MediaProcessingTrigger 및 새 BackgroundTaskBuilder를 만듭니다.To register the background task, create a new MediaProcessingTrigger and a new BackgroundTaskBuilder. 나중에 식별할 수 있도록 백그라운드 작업 빌더의 이름을 설정 합니다.Set the name of the background task builder so that you can identify it later. Taskentrypoint 를 매니페스트 파일에서 사용한 것과 같은 네임 스페이스 및 클래스 이름 문자열로 설정 합니다.Set the TaskEntryPoint to the same namespace and class name string you used in the manifest file. 트리거 속성을 MediaProcessingTrigger 인스턴스로 설정 합니다.Set the Trigger property to the MediaProcessingTrigger instance.

작업을 등록 하기 전에 alltasks 컬렉션을 반복 하 고 BackgroundTaskBuilder.Name 속성에 지정한 이름을 가진 작업에 대해 등록 취소 를 호출 하 여 이전에 등록 된 작업의 등록을 취소 해야 합니다.Before registering the task, make sure you unregister any previously registered tasks by looping through the AllTasks collection and calling Unregister on any tasks that have the name you specified in the BackgroundTaskBuilder.Name property.

Register를 호출 하 여 백그라운드 작업을 등록 합니다.Register the background task by calling Register. 완료 된 이벤트와 진행 중인 이벤트에 대 한 처리기를 등록 합니다.Register handlers for the Completed and Progress events.

private void RegisterBackgroundTask()
{
    // New a MediaProcessingTrigger
    mediaProcessingTrigger = new MediaProcessingTrigger();

    var builder = new BackgroundTaskBuilder();

    builder.Name = backgroundTaskBuilderName;
    builder.TaskEntryPoint = "MediaProcessingBackgroundTask.MediaProcessingTask";
    builder.SetTrigger(mediaProcessingTrigger);

    // unregister old ones
    foreach (var cur in BackgroundTaskRegistration.AllTasks)
    {
        if (cur.Value.Name == backgroundTaskBuilderName)
        {
            cur.Value.Unregister(true);
        }
    }

    taskRegistration = builder.Register();
    taskRegistration.Progress += new BackgroundTaskProgressEventHandler(OnProgress);
    taskRegistration.Completed += new BackgroundTaskCompletedEventHandler(OnCompleted);

    return;
}

일반적인 앱은 OnNavigatedTo 이벤트와 같이 앱이 처음 시작 될 때 백그라운드 작업을 등록 합니다.A typical app will register their background task when the app is initially launched, such as in the OnNavigatedTo event.

MediaProcessingTrigger 개체의 requestasync 메서드를 호출 하 여 백그라운드 작업을 시작 합니다.Launch the background task by calling the MediaProcessingTrigger object's RequestAsync method. 이 메서드에서 반환 된 MediaProcessingTriggerResult 개체를 사용 하면 백그라운드 작업이 성공적으로 시작 되었는지 여부를 알 수 있으며, 그렇지 않으면 백그라운드 작업이 시작 되지 않은 이유를 알 수 있습니다.The MediaProcessingTriggerResult object returned by this method lets you know whether the background task was started successfully, and if not, lets you know why the background task wasn't launched.

private async void LaunchBackgroundTask()
{
    var success = true;

    if (mediaProcessingTrigger != null)
    {
        MediaProcessingTriggerResult activationResult;
        activationResult = await mediaProcessingTrigger.RequestAsync();

        switch (activationResult)
        {
            case MediaProcessingTriggerResult.Allowed:
                // Task starting successfully
                break;

            case MediaProcessingTriggerResult.CurrentlyRunning:
            // Already Triggered

            case MediaProcessingTriggerResult.DisabledByPolicy:
            // Disabled by system policy

            case MediaProcessingTriggerResult.UnknownError:
                // All other failures
                success = false;
                break;
        }

        if (!success)
        {
            // Unregister the media processing trigger background task
            taskRegistration.Unregister(true);
        }
    }

}

일반적인 앱은 UI 컨트롤의 Click 이벤트와 같이 사용자 상호 작용에 대 한 응답으로 백그라운드 작업을 시작 합니다.A typical app will launch the background task in response to user interaction, such as in the Click event of a UI control.

OnProgress 이벤트 처리기는 백그라운드 태스크가 작업 진행률을 업데이트할 때 호출 됩니다.The OnProgress event handler is called when the background task updates the progress of the operation. 이 기회를 사용 하 여 진행률 정보로 UI를 업데이트할 수 있습니다.You can use this opportunity to update your UI with progress information.

private void OnProgress(IBackgroundTaskRegistration task, BackgroundTaskProgressEventArgs args)
{
    string progress = "Progress: " + args.Progress + "%";
    Debug.WriteLine(progress);
}

Oncompleted 이벤트 처리기는 백그라운드 작업의 실행이 완료 될 때 호출 됩니다.The OnCompleted event handler is called when the background task has finished running. 이는 UI를 업데이트 하 여 사용자에 게 상태 정보를 제공 하는 또 다른 기회입니다.This is another opportunity to update your UI to give status information to the user.

private void OnCompleted(IBackgroundTaskRegistration task, BackgroundTaskCompletedEventArgs args)
{
    Debug.WriteLine(" background task complete");
}