[Windows 8 App]多媒體-----【音頻與視頻的轉碼】(下)

[Windows 8 App]多媒體-----【音頻與視頻的轉碼】(下)

 

前台設計完畢後,我們開啟【MainPage.xaml.cs】來寫後台的程式碼

後台的程式碼有點多,請慢慢看

 

首先在應用程式的構造方法中使用 TranscodeVideoFile 方法,以便完成轉碼的操作


public MainPage()
        {
            this.InitializeComponent();
            TranscodeVideoFile();
            //執行轉碼操作
        }

接下來寫 TranscodeVideoFile 方法,程式碼如下

 

這是轉碼操作的程式碼


async void TranscodeVideoFile()
        {
            Windows.Storage.StorageFile sourcce;
            Windows.Storage.StorageFile destination;
            //建立FileOpenPicker的對象

            var openPicker = new Windows.Storage.Pickers.FileOpenPicker();
            //設置初始選取文件的位置

            openPicker.SuggestedStartLocation = Windows.Storage.Pickers.PickerLocationId.VideosLibrary;
            //設置選取文件的類型

            openPicker.FileTypeFilter.Add(".mp4");
            openPicker.FileTypeFilter.Add(".avi");
            //啟動選擇器並取得文件

            sourcce = await openPicker.PickSingleFileAsync();
            //建立 FileSavePicker 的對象

            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" });
            //啟動文件的保存器

            destination = await savePicker.PickSaveFileAsync();
            //執行轉碼的TranscoderFile方法
            TranscodeFile(sourcce, destination);
        }

 

在上面的代碼中,先建立一個FileOpenPicker的對象OpenPicker,是用來選取要轉碼的文件

再來看到OpenPicker的SuggestedStartLocation屬性,這是用來選取文件的位置

OpenPicker的FileTypeFilter屬性,是用來篩選文件的類型

之後就使用PickSingleFileAsync來啟動文件的選擇器

並將選擇的文件儲存在StorageFile的Source對象中

再來建立一個FileSavePicker的對象SavePicker,這是要用來儲存轉碼完成後的媒體文件

然後,並設定SuggestedStartLocation屬性來指定儲存的位置

使用DefaultFileExtension屬性,來設定文件轉碼後的格式

SuggestedFileName屬性,是設定轉碼後文件的名稱

再使用FileTypeChoices屬性,來設定可儲存的文件類型

這時使用savePicker的PickSaveFileAsync方法來啟動文件保存器

並將文件儲存在StorageFile的destination對象中

這些是上面程式碼的部分

 

下面是TranscodeVideoFile()中的TranscodeFile方法程式碼

這個方法中有兩個StorageFile的參數,分別是轉碼操作的來源文件和目標文件

程式碼如下:


async void TranscodeFile(StorageFile srcFile, StorageFile destFile)
        {
            MediaEncodingProfile profile = MediaEncodingProfile.CreateMp4(VideoEncodingQuality.HD720p);
            //創建編碼配置文件

            MediaTranscoder transcoder = new MediaTranscoder();
            //建立一個MediaTranscoder用於媒體文件的轉碼

            PrepareTranscodeResult prepareOp = await transcoder.PrepareFileTranscodeAsync(srcFile, destFile, profile);
            //PrepareFileTranscodeAsync方法是非同步的,轉碼的動作在後台,應用程式介面能可以正常反應

            if (prepareOp.CanTranscode)
            {
                var transcodeOp = prepareOp.TranscodeAsync();

                transcodeOp.Progress += new AsyncActionProgressHandler<double>(TranscodeProgress);
                //新增TranscodeProgress方法,在應用程式介面顯示轉碼的進度

                transcodeOp.Completed += new AsyncActionWithProgressCompletedHandler<double>(TranscodeComplete);
                //新增TranscodeComplete方法,在應用程式介面顯示晚誠、取消的訊息
            }


            else
            {
                //向應用程式介面顯示錯誤訊息
                switch (prepareOp.FailureReason)
                {
                    case TranscodeFailureReason.CodecNotFound:
                        txtDisplay.Text = "未找到解碼器! ";
                        break;
                    case TranscodeFailureReason.InvalidProfile:
                        txtDisplay.Text = "無效的編碼文件! ";
                        break;
                    default:
                        txtDisplay.Text = "未知錯誤! ";
                        break;
                }
            }
        }

VideoEncodingQuality.HD720p 這是設置轉碼的目標分辨率

HD720p 表示 1280x720 像素

建立一個MediaTranscoder類型的對象transcoder,用來文件的轉碼

用transcoder對象PrepareFileTranscodeAsync的方法

並對方法傳入來源文件srcFile、目標文件destFile、編碼配置的文件對象profile

將這方法傳回的值儲存在PrepareTranscodeResult的prepareOp中

然後prepareOp的CanTranscode屬性,是判斷是否可以進行轉碼操作

如果可以轉碼的話,則使用prepareOp的TranscodeAsync()方法來進行轉碼

並將轉碼的值傳回給transcodeOp

接著對transcodeOp的Progress和Completed事件添加TranscodeProgress和TranscodeComplete的事件處理方法

這兩個方法是用來向應用程式界面顯示轉碼的進度和轉碼完成、取消的訊息

 

接下來是transcodeOp的Progress事件的事件處理方法TranscodeProgress() 之程式碼:


async void TranscodeProgress(IAsyncActionWithProgress<double> asyncInfo, double percent)
        {
            await Dispatcher.RunAsync(Windows.UI.Core.CoreDispatcherPriority.Normal, () =>
            {
                txtProgress.Text = "轉碼進度:" + percent.ToString().Split('.')[0] + "%";
            });
        }

上面是轉碼進度的訊息

 

下面是transcodeOp的Completed事件的事件處理方法TranscodeComplete() 之程式碼:


async void TranscodeComplete(IAsyncActionWithProgress<double> asyncInfo, AsyncStatus status)
        {
            await Dispatcher.RunAsync(Windows.UI.Core.CoreDispatcherPriority.Normal, () =>
            {
                if (asyncInfo.Status == AsyncStatus.Completed)
                {
                    txtDisplay.Text = "轉碼操作已完成.";
                }
                else if (asyncInfo.Status == AsyncStatus.Canceled)
                {
                    txtDisplay.Text = "轉碼操作已取消.";
                }
                else
                {
                    txtDisplay.Text = asyncInfo.ErrorCode.Message;
                }
            });
        }

 

上面是顯示轉碼的完成、取消訊息

 

我們把所有程式碼做個整合:


using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using Windows.Foundation;
using Windows.Foundation.Collections;
using Windows.Media.MediaProperties;
using Windows.Media.Transcoding;
using Windows.Storage;
using Windows.UI.Xaml;
using Windows.UI.Xaml.Controls;
using Windows.UI.Xaml.Controls.Primitives;
using Windows.UI.Xaml.Data;
using Windows.UI.Xaml.Input;
using Windows.UI.Xaml.Media;
using Windows.UI.Xaml.Navigation;
using Windows.Storage;

// 空白頁項目範本已記錄在 http://go.microsoft.com/fwlink/?LinkId=234238

namespace MediaTrans
{
    /// <summary>
    /// 可以在本身使用或巡覽至框架內的空白頁面。
    /// </summary>
    public sealed partial class MainPage : Page
    {
        public MainPage()
        {
            this.InitializeComponent();
            TranscodeVideoFile();
            //執行轉碼操作
        }

        async void TranscodeVideoFile()
        {
            Windows.Storage.StorageFile sourcce;
            Windows.Storage.StorageFile destination;
            //建立FileOpenPicker的對象

            var openPicker = new Windows.Storage.Pickers.FileOpenPicker();
            //設置初始選取文件的位置

            openPicker.SuggestedStartLocation = Windows.Storage.Pickers.PickerLocationId.VideosLibrary;
            //設置選取文件的類型

            openPicker.FileTypeFilter.Add(".mp4");
            openPicker.FileTypeFilter.Add(".avi");
            //啟動選擇器並取得文件

            sourcce = await openPicker.PickSingleFileAsync();
            //建立 FileSavePicker 的對象

            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" });
            //啟動文件的保存器

            destination = await savePicker.PickSaveFileAsync();
            //執行轉碼的TranscoderFile方法
            TranscodeFile(sourcce, destination);
        }
        async void TranscodeFile(StorageFile srcFile, StorageFile destFile)
        {
            MediaEncodingProfile profile = MediaEncodingProfile.CreateMp4(VideoEncodingQuality.HD720p);
            //創建編碼配置文件

            MediaTranscoder transcoder = new MediaTranscoder();
            //建立一個MediaTranscoder用於媒體文件的轉碼

            PrepareTranscodeResult prepareOp = await transcoder.PrepareFileTranscodeAsync(srcFile, destFile, profile);
            //PrepareFileTranscodeAsync方法是非同步的,轉碼的動作在後台,應用程式介面能可以正常反應

            if (prepareOp.CanTranscode)
            {
                var transcodeOp = prepareOp.TranscodeAsync();

                transcodeOp.Progress += new AsyncActionProgressHandler<double>(TranscodeProgress);
                //新增TranscodeProgress方法,在應用程式介面顯示轉碼的進度

                transcodeOp.Completed += new AsyncActionWithProgressCompletedHandler<double>(TranscodeComplete);
                //新增TranscodeComplete方法,在應用程式介面顯示晚誠、取消的訊息
            }


            else
            {
                //向應用程式介面顯示錯誤訊息
                switch (prepareOp.FailureReason)
                {
                    case TranscodeFailureReason.CodecNotFound:
                        txtDisplay.Text = "未找到解碼器! ";
                        break;
                    case TranscodeFailureReason.InvalidProfile:
                        txtDisplay.Text = "無效的編碼文件! ";
                        break;
                    default:
                        txtDisplay.Text = "未知錯誤! ";
                        break;
                }
            }
        }

        //下面是顯示轉碼進度的訊息
        async void TranscodeProgress(IAsyncActionWithProgress<double> asyncInfo, double percent)
        {
            await Dispatcher.RunAsync(Windows.UI.Core.CoreDispatcherPriority.Normal, () =>
            {
                txtProgress.Text = "轉碼進度:" + percent.ToString().Split('.')[0] + "%";
            });
        }

        //下面是顯示轉碼完成、取消的訊息
        async void TranscodeComplete(IAsyncActionWithProgress<double> asyncInfo, AsyncStatus status)
        {
            await Dispatcher.RunAsync(Windows.UI.Core.CoreDispatcherPriority.Normal, () =>
            {
                if (asyncInfo.Status == AsyncStatus.Completed)
                {
                    txtDisplay.Text = "轉碼操作已完成.";
                }
                else if (asyncInfo.Status == AsyncStatus.Canceled)
                {
                    txtDisplay.Text = "轉碼操作已取消.";
                }
                else
                {
                    txtDisplay.Text = asyncInfo.ErrorCode.Message;
                }
            });
        }


        /// <summary>
        /// 在此頁面即將顯示在框架中時叫用。
        /// </summary>
        /// <param name="e">描述如何到達此頁面的事件資料。Parameter
        /// 屬性通常用來設定頁面。</param>
        protected override void OnNavigatedTo(NavigationEventArgs e)
        {
        }
    }
}

 

這是轉碼的畫面:

轉碼中

86

 

轉碼完畢

85