如何錄製音訊或視訊 (HTML)
[ 本文的目標對象是撰寫 Windows 執行階段 App 的 Windows 8.x 和 Windows Phone 8.x 開發人員。如果您正在開發適用於 Windows 10 的 App,請參閱 最新文件 ]
您可以從相機錄製視訊和/或從麥克風錄製音訊。
指示
初始化 MediaCaptureSettings
MediaCaptureSettings 屬性會提供 MediaCapture 物件的組態設定。如下列範例所示,使用 MediaCaptureInitializationSettings 類別來初始化這些屬性。
// Initialize the MediaCaptureInitialzationSettings.
function initCaptureSettings() {
captureInitSettings = null;
captureInitSettings = new Windows.Media.Capture.MediaCaptureInitializationSettings();
captureInitSettings.audioDeviceId = "";
captureInitSettings.videoDeviceId = "";
captureInitSettings.streamingCaptureMode = Windows.Media.Capture.StreamingCaptureMode.audioAndVideo;
captureInitSettings.photoCaptureSource = Windows.Media.Capture.PhotoCaptureSource.videoPreview;
if (deviceList.length > 0)
captureInitSettings.videoDeviceId = deviceList[0].id;
}
建立 MediaCapture 物件
MediaCapture 物件包含您拍攝視訊時所需的方法和非同步作業。
oMediaCapture = new Windows.Media.Capture.MediaCapture();
初始化 MediaCapture 物件
使用 MediaCapture.InitializeAsync 方法來初始化 MediaCapture物件。根據預設,InitializeAsync 會使用預設的視訊擷取裝置,而且會拍攝音訊或視訊。另一種方法是,您可以建立和初始化自己的 MediaCaptureInitializationSettings 物件,然後將它傳送到 InitializeAsync 方法。
// Create and initialze the MediaCapture object.
function initMediaCapture() {
oMediaCapture = null;
oMediaCapture = new Windows.Media.Capture.MediaCapture();
oMediaCapture.initializeAsync(captureInitSettings).then (function (result) {
createProfile();
}, errorHandler);
}
建立編碼設定檔
編碼設定檔中包含為目的地檔案進行編碼時所需的全部設定。Windows.Media.MediaProperties API 提供多個建立 MediaEncodingProfile 物件的選項。
Windows.Media.MediaProperties 命名空間提供一組預先定義的編碼設定檔:
- AAC 音訊 (M4A)
- MP3 音訊
- Windows Media 音訊 (WMA)
- MP4 視訊 (H.264 視訊加 AAC 音訊)
- Windows Media 視訊 (WMV)
清單中的前三個設定檔只包含音訊。其他兩個包含視訊和音訊。
下列程式碼會建立 MP4 視訊的設定檔。
// Create a profile.
function createProfile() {
profile = Windows.Media.MediaProperties.MediaEncodingProfile.createMp4(
Windows.Media.MediaProperties.VideoEncodingQuality.hd720p);
}
靜態 CreateMp4 方法會建立 MP4 編碼設定檔。這個方法的參數會提供視訊的目標解析度。在這種情況下,VideoEncodingQuality.HD720p 表示 1280 x 720 個像素,每秒 30 個畫面。("720p" 表示每一個畫面有 720 條漸進式掃描線)。建立預先定義設定檔的其他方法都是沿用這個模式。
另一種方法是,您可以使用 Windows.Media.MediaProperties.MediaEncodingProfile.CreateFromFileAsync 方法來建立一個符合現有媒體檔案的設定檔。或者,如果您知道自己所需的正確編碼設定,您可以建立新的 Windows.Media.MediaProperties.MediaEncodingProfile 物件,然後填入所有設定檔詳細資料。
開始錄製
若要開始拍攝視訊並儲存到檔案中,請為已拍攝的視訊建立一個檔案。然後呼叫 StartRecordToStorageFileAsync 方法,傳入 MediaEncodingProfile 和目的地儲存檔案。
// Start the video capture.
function startMediaCaptureSession() {
Windows.Storage.KnownFolders.videosLibrary.createFileAsync("cameraCapture.mp4", Windows.Storage.CreationCollisionOption.generateUniqueName).then(function (newFile) {
storageFile = newFile;
oMediaCapture.startRecordToStorageFileAsync(profile, storageFile).then(function (result) {
}, errorHandler);
} );
}
停止錄製
若要停止拍攝視訊,請呼叫 StopRecordAsync 方法。
// Stop the video capture.
function stopMediaCaptureSession() {
oMediaCapture.stopRecordAsync().then(function (result) {
}, errorHandler);
}
完整範例
下列範例說明如何錄製視訊並儲存成一個檔案。
var oMediaCapture;
var profile;
var captureInitSettings;
var deviceList = new Array();
var recordState = false;
var storageFile;
function errorHandler(e) {
sdkSample.displayStatus(e.message + ", Error Code: " + e.code.toString(16));
}
// Begin initialization.
function initialization() {
document.getElementById("message").innerHTML = "Initialization started.";
enumerateCameras();
}
// Identify available cameras.
function enumerateCameras() {
var deviceInfo = Windows.Devices.Enumeration.DeviceInformation;
deviceInfo.findAllAsync(Windows.Devices.Enumeration.DeviceClass.videoCapture).then(function (devices) {
// Add the devices to deviceList
if (devices.length > 0) {
for (var i = 0; i < devices.length; i++) {
deviceList.push(devices[i]);
}
initCaptureSettings();
initMediaCapture();
document.getElementById("message").innerHTML = "Initialization complete.";
} else {
sdkSample.displayError("No camera device is found ");
}
}, errorHandler);
}
// Initialize the MediaCaptureInitialzationSettings.
function initCaptureSettings() {
captureInitSettings = null;
captureInitSettings = new Windows.Media.Capture.MediaCaptureInitializationSettings();
captureInitSettings.audioDeviceId = "";
captureInitSettings.videoDeviceId = "";
captureInitSettings.streamingCaptureMode = Windows.Media.Capture.StreamingCaptureMode.audioAndVideo;
captureInitSettings.photoCaptureSource = Windows.Media.Capture.PhotoCaptureSource.videoPreview;
if (deviceList.length > 0)
captureInitSettings.videoDeviceId = deviceList[0].id;
}
// Create a profile.
function createProfile() {
profile = Windows.Media.MediaProperties.MediaEncodingProfile.createMp4(
Windows.Media.MediaProperties.VideoEncodingQuality.hd720p);
}
// Create and initialze the MediaCapture object.
function initMediaCapture() {
oMediaCapture = null;
oMediaCapture = new Windows.Media.Capture.MediaCapture();
oMediaCapture.initializeAsync(captureInitSettings).then (function (result) {
createProfile();
}, errorHandler);
}
// Start the video capture.
function startMediaCaptureSession() {
Windows.Storage.KnownFolders.videosLibrary.createFileAsync("cameraCapture.mp4", Windows.Storage.CreationCollisionOption.generateUniqueName).then(function (newFile) {
storageFile = newFile;
oMediaCapture.startRecordToStorageFileAsync(profile, storageFile).then(function (result) {
}, errorHandler);
} );
}
// Stop the video capture.
function stopMediaCaptureSession() {
oMediaCapture.stopRecordAsync().then(function (result) {
}, errorHandler);
}
適當清理 MediaCapture 資源
警告
當應用程式暫停時,適當的關閉和處理 MediaCapture 物件以及相關物件非常重要。若未執行此動作,可能會干擾其他應用程式存取裝置的相機,造成使用者對您的應用程式產生負面的使用者體驗。
在 Windows Phone,請清理 oncheckpoint 應用程式週期事件處理常式中的 MediaCapture 資源。在 Windows,請使用 SoundLevelChanged 事件並檢查音量是否為靜音。如果是靜音,則清理 MediaCapture 資源。如果事件指示任何其他音量,請使用此事件重新建立。請注意,這個事件將不會觸發您的程式碼,即使您在應用程式執行時手動將聲音設為靜音或解除靜音也一樣。因此,此事件可有效提供與手機上暫停和繼續相同的功能。這是必要的,因為在 Windows 上,使用者可以在應用程式之間切換,不需暫停目前的應用程式。
您應該清理 Windows Phone 的 oncheckpoint 事件或 Windows 的 SoundLevelChanged 中的媒體擷取資源,如本指導方針上述所說明。宣告一些變數以儲存 MediaCapture 物件和指出應用程式目前正在錄製或預覽影片的布林值,是個不錯的方法。接著,建立一個可停止錄製或預覽的函式,呼叫 MediaCapture 物件的 close 方法並將它設為 null。下列程式碼顯示實作此方法的範例。
function cleanupCaptureResources()
{
var promises = [];
if (mediaCapture) {
if (isRecording) {
promises.push(mediaCapture.stopRecordAsync().then(function () {
isRecording = false;
}));
}
promises.push(new WinJS.Promise(function (complete) {
mediaCapture.close();
mediaCapture = null;
complete();
}));
}
return WinJS.Promise.join(promises).done(null, errorHandler);
}
最後,將下列程式碼新增至 oncheckpoint 事件處理常式。使用 Promise 呼叫清理方法相當重要。這可確保系統在暫停應用程式之前先讓方法完成。
app.oncheckpoint = function (args) {
args.setPromise(
cleanupCaptureResources()
);
};