在 WinUI 3 應用程式中使用 MediaCapture 進行基本相片、視訊和音訊擷取
本文說明使用 MediaCapture 類別擷取相片和視訊的最簡單方式。
MediaCapture 類別會公開一組健全的 API,提供對擷取管線的低階控制,並啟用進階擷取案例,但本文旨在協助您快速且輕鬆地將基本媒體擷取新增至您的應用程式。 若要深入瞭解 MediaCapture 所提供的
初始化 MediaCapture 物件
本文所述的所有擷取方法都需要初始化 MediaCapture 物件的第一個步驟。 這包括具現化對象、選取擷取裝置、設定初始化參數,然後呼叫 InitializeAsync。 相機應用程式通常會使用 mediaPlayerElement,在 UI 中擷取相片或視訊時顯示相機預覽。 如需初始化 MediaCapture 並在 XAML UI 中顯示預覽的逐步解說,請參閱 在 WinUI 3 應用程式中顯示相機預覽。 本文中的程式代碼範例會假設已建立 MediaCapture 的初始化實例。
將相片擷取至SoftwareBitmap
SoftwareBitmap 類別提供跨多個功能之影像的通用表示。 如果您想要擷取相片,然後立即在應用程式中使用擷取的影像,例如在 XAML 中顯示,而不是將影像儲存為檔案,則您應該將影像擷取至 SoftwareBitmap。 您仍然可以選擇稍後將映像儲存到磁碟。
使用 LowLagPhotoCapture 類別,將相片擷取至 SoftwareBitmap。 呼叫 PrepareLowLagPhotoCaptureAsync來取得這個類別的實例,並傳入 ImageEncodingProperties 物件,以指定您想要的影像格式。 CreateUncompressed 會建立具有指定像素格式的未壓縮編碼。 呼叫 CaptureAsync來起始相片擷取,這會傳回 CapturedPhoto 物件。 藉由先存取 Frame 屬性,然後存取 SoftwareBitmap 屬性,以獲得 SoftwareBitmap。
您可以重複呼叫 captureAsync 來擷取多個相片。 當您完成擷取時,請呼叫 FinishAsync 來關閉 LowLagPhotoCapture 會話,並釋放相關聯的資源。 呼叫 FinishAsync之後,若要再次開始擷取相片,您必須再次呼叫 PrepareLowLagPhotoCaptureAsync,以重新初始化擷取會話,然後呼叫 CaptureAsync。
// Prepare and capture photo
var lowLagCapture = await m_mediaCapture.PrepareLowLagPhotoCaptureAsync(ImageEncodingProperties.CreateUncompressed(MediaPixelFormat.Bgra8));
var capturedPhoto = await lowLagCapture.CaptureAsync();
var softwareBitmap = capturedPhoto.Frame.SoftwareBitmap;
// Capture more photos, if desired.
// Then call FinishAsync to clean up resources
await lowLagCapture.FinishAsync();
將相片擷取至記憶體數據流
您可以使用 MediaCapture 將相片擷取到記憶體內部數據流,然後您可以使用該數據流將相片從串流轉碼到磁碟上的檔案。
建立 InMemoryRandomAccessStream,然後呼叫 CapturePhotoToStreamAsync 來擷取相片到數據流,並傳入數據流和 ImageEncodingProperties 物件,以指定應該使用的影像格式。 您可以自行初始化物件來建立自定義編碼屬性,但 類別會提供靜態方法,例如 ImageEncodingProperties.CreateJpeg,以取得常見的編碼格式。
建立 BitmapDecoder,從記憶體資料流中解碼圖像。 建立 BitmapEncoder 並呼叫 CreateForTranscodingAsync以將影像編碼為檔案。
您可以選擇性地建立 BitmapPropertySet 對象,然後在影像編碼器上呼叫 SetPropertiesAsync,以在影像檔中包含相片的相關元數據。 如需編碼屬性的詳細資訊,請參閱 影像元資料。
最後,呼叫編碼器物件上的 FlushAsync,將內存流中的相片轉碼至檔案。
// Prepare and capture photo
var lowLagCapture = await m_mediaCapture.PrepareLowLagPhotoCaptureAsync(ImageEncodingProperties.CreateUncompressed(MediaPixelFormat.Bgra8));
var capturedPhoto = await lowLagCapture.CaptureAsync();
var softwareBitmap = capturedPhoto.Frame.SoftwareBitmap;
// Capture more photos, if desired.
// Then call FinishAsync to clean up resources
await lowLagCapture.FinishAsync();
拍攝影片
使用 LowLagMediaRecording 類別,快速將影片擷取新增至您的應用程式。
首先,LowLagMediaRecording 在擷取視訊時必須保存,因此請將 類別變數宣告為物件。
LowLagMediaRecording m_mediaRecording;
呼叫 PrepareLowLagRecordToStorageFileAsync 來初始化媒體錄製,傳入儲存檔案和 MediaEncodingProfile 物件,以指定視訊的編碼方式。 類別提供靜態方法,例如 CreateMp4,用於建立常見的視訊編碼配置檔。 呼叫 StartAsync 開始擷取影片。
var myVideos = await Windows.Storage.StorageLibrary.GetLibraryAsync(Windows.Storage.KnownLibraryId.Videos);
StorageFile file = await myVideos.SaveFolder.CreateFileAsync("video.mp4", CreationCollisionOption.GenerateUniqueName);
m_mediaRecording = await m_mediaCapture.PrepareLowLagRecordToStorageFileAsync(
MediaEncodingProfile.CreateMp4(VideoEncodingQuality.Auto), file);
m_mediaCapture.RecordLimitationExceeded += m_mediaCapture_RecordLimitationExceeded;
await m_mediaRecording.StartAsync();
await m_mediaRecording.StopAsync();
您可以繼續呼叫 StartAsync,並 StopAsync 來擷取其他影片。 當您完成擷取影片時,請呼叫 FinishAsync 來處置擷取會話並清除相關聯的資源。 呼叫完畢後,您必須再次呼叫 PrepareLowLagRecordToStorageFileAsync,重新初始化擷取工作階段,然後再呼叫 StartAsync。
await m_mediaRecording.FinishAsync();
擷取視訊時,您應該註冊 RecordLimitationExceeded 事件 MediaCapture 對象的處理程式,如果您超過目前三個小時的單一錄製限制,操作系統將會引發此事件。 在事件的處理程式中,您應該呼叫 StopAsync來完成錄製。
private async void m_mediaCapture_RecordLimitationExceeded(MediaCapture sender)
{
await m_mediaRecording.StopAsync();
DispatcherQueue.TryEnqueue(() =>
{
tbStatus.Text = "Record limitation exceeded.";
});
}
您可以暫停視訊錄製,然後繼續錄製,而不需建立個別的輸出檔案,方法是呼叫 PauseAsync,然後呼叫 ResumeAsync。
await m_mediaRecording.PauseAsync(Windows.Media.Devices.MediaCapturePauseBehavior.ReleaseHardwareResources);
await m_mediaRecording.ResumeAsync();
呼叫 PauseWithResultAsync 會傳回 MediaCapturePauseResult 物件。 LastFrame 屬性是代表最後一個畫面的 VideoFrame 物件。 若要在 XAML 中顯示影格,請取得視訊影格的 SoftwareBitmap 表示法。 目前僅支援具有預乘或空白 Alpha 通道的 BGRA8 格式影像,因此如果需要,請呼叫 Convert,以取得正確的格式。 PauseWithResultAsync 也會傳回在上一段錄製過程中的視訊持續時間,以防您需要追蹤整個過程中已錄製的總時間。
您也可以透過呼叫 StopWithResultAsync 在停止影片播放時得到結果畫面。
播放和編輯擷取的視訊檔案
將影片擷取到檔案之後,您可能會想要載入該檔案,並在應用程式的使用者介面中播放。 您可以使用 MediaPlayerElement XAML 控制件和相關聯的 MediaPlayer來執行此動作。 如需在 XAML 頁面中播放媒體的資訊,請參閱 使用 MediaPlayer 播放音訊和視訊。
[TBD - WinUI 是否支援 /建議使用 MediaComposition 架構?]
您也可以從視訊檔案呼叫 CreateFromFileAsync,從視訊檔案建立 MediaClip 物件。 MediaComposition 提供基本的視訊編輯功能,例如排列 MediaClip 物件的序列、修剪視訊長度、建立圖層、新增背景音樂,以及套用視訊效果。 如需使用媒體組合的詳細資訊,請參閱 媒體組合和編輯。
捕捉音訊
您可以使用上面所示的相同技術來擷取視訊,快速將音訊擷取新增至您的應用程式。 呼叫 prepareLowLagRecordToStorageFileAsync 以初始化擷取會話,傳入檔案和 MediaEncodingProfile,CreateMp3 靜態方法所產生的範例。 若要開始錄製,請呼叫 startAsync 。
TBD - 此程式代碼拋出「請求在目前狀態下無效。」
m_mediaCapture.RecordLimitationExceeded += m_mediaCapture_RecordLimitationExceeded;
var myVideos = await Windows.Storage.StorageLibrary.GetLibraryAsync(Windows.Storage.KnownLibraryId.Videos);
StorageFile file = await myVideos.SaveFolder.CreateFileAsync("audio.mp3", CreationCollisionOption.GenerateUniqueName);
m_mediaRecording = await m_mediaCapture.PrepareLowLagRecordToStorageFileAsync(
MediaEncodingProfile.CreateMp3(AudioEncodingQuality.High), file);
await m_mediaRecording.StartAsync();
呼叫 StopAsync 以停止音訊錄製。
await m_mediaRecording.StopAsync();
您可以呼叫 StartAsync 和 StopAsync 多次錄製數個音訊檔案。 當您完成擷取音訊時,請呼叫 FinishAsync 以處置擷取會話並清除相關聯的資源。 這次呼叫之後,您必須再次呼叫 PrepareLowLagRecordToStorageFileAsync,以重新初始化擷取會話,然後再呼叫 StartAsync。
如需偵測系統何時變更音訊擷取數據流音訊等級的資訊,請參閱 偵測並響應系統的音訊層級變更。