次に、[ソリューション・エクスプローラー]内のMainWindow.xamlを展開して表示される、「MainWindow.xaml.vb」のコードを記述する。
ここではコードが長くなるため、名前空間の読み込み、メンバー変数の宣言は一部省略している。全てのコードは、サンプルをダウンロードして「MainWindow.xaml.vb」ファイルで確認してほしい。
Private Async Function DataShow() As Task AppBar1.Visibility = Xaml.Visibility.Visible Try myRecordMediaCapture = New MediaCapture myCaptureInitSetting = New MediaCaptureInitializationSettings myCaptureInitSetting.AudioDeviceId = String.Empty myCaptureInitSetting.StreamingCaptureMode = StreamingCaptureMode.Audio Await myRecordMediaCapture.InitializeAsync(myCaptureInitSetting) myProfile = MediaEncodingProfile.CreateMp4(VideoEncodingQuality.Auto) Dim myStorageFolder As StorageFolder = Windows.Storage.KnownFolders.PicturesLibrary Dim mySubFolder = Await myStorageFolder.CreateFolderAsync("ImageVoiceRecord", CreationCollisionOption.OpenIfExists) Dim myFile = Await mySubFolder.GetFilesAsync() If myFile.Count > 0 Then ichiranButton.IsEnabled = True Else PhotoArea.Children.Clear() ichiranButton.IsEnabled = False End If For Each result In myFile If result.Path.Contains("Thumbs.db") Then Await result.DeleteAsync End If Next cameraComboBox.Items.Clear() myCamera = Await DeviceInformation.FindAllAsync(DeviceClass.VideoCapture) For i As Integer = 0 To myCamera.Count - 1 Dim cameraInfo = myCamera(i) cameraComboBox.Items.Add(cameraInfo.Name) Next If cameraNo < 0 Then cameraComboBox.SelectedIndex = 0 shutterButton.IsEnabled = True Else cameraComboBox.SelectedIndex = cameraNo shutterButton.IsEnabled = True End If Catch ErrorShow() End Try End Function
以降、上記コードの中身を詳細に見ていこう。
まず、非同期処理で行われるためメソッドの先頭にAsyncを追加している。
次に、新しいMediaCaptureのインスタンスを作成する。
MediaCaptureオブジェクトの初期化設定を含む、新しいMediaCaptureInitializationSettingsクラスのインスタンスを作成し、myCaptureInitSettingメンバー変数で参照する。
マイクのDeviceInformation.Idを取得する、AudioDeviceIdをString.Emptyで初期化しておく。
ストリーミングモードを設定する、StreamingCaptureModeプロパティに、オーディオのみのキャプチャを指定する。
MediaCaptureオブジェクトを初期化する、InitializeAsyncメソッドで、オーディオのみのキャプチャを初期化する。
CreateMp4メソッドで、エンコーディングプロファイルを作成する。エンコーディング形式をAutoに指定する。
ピクチャライブラリーのImageVoiceRecordサブフォルダーにアクセスする。このサブフォルダー内のファイルをGetFilesAsyncメソッドで取得する。ファイルが存在すれば、「一覧」アイコンの使用を可能にし、そうでない場合は、使用不可とする。
ImageVoiceRecordサブフォルダー内にThumbs.dbが作成されていたら、これを削除する。このファイルは自動的に作成されるファイルだ。
cameraComboBox内を一度クリアする。
FindAllAsyncメソッドで全てのビデオキャプチャデバイスを列挙して、DeviceInfomationオブジェクトのコレクションである、myCameraコレクション変数で参照する。
Webカメラが実装されている場合は、コレクション変数myCameraが格納しているデバイスの個数分、繰り返し変数iで反復処理を行う。DeviceInfomationの列挙体である、変数cameraInfoで、コレクション変数myCameraが格納しているデバイスを参照させる。
cameraComboBoxにAddメソッドで取得したデバイス名を追加する。フロントカメラやリアカメラを実装しているタブレットPCでは、2つのデバイス名が追加表示されるので、cameraComboBoxのSelectedIndexが0より小さい場合、つまりデバイスが選択されていない場合は、最初のデバイスを選択する。
「写真を撮る」アイコンの使用を可能にする。選択されている場合は、それを選択状態にする。
エラーが発生した場合は、ErrorShowメソッドを実行する。
このアプリの肝となる処理。取った画像に音声を関連付ける。
Private Async Sub shutterButton_Click(sender As Object, e As RoutedEventArgs) Handles shutterButton.Click PhotoArea.Children.Clear() MediaElement1.Play() Dim myFolder As StorageFolder = Windows.Storage.KnownFolders.PicturesLibrary Dim mySubFolder = Await myFolder.CreateFolderAsync("ImageVoiceRecord", CreationCollisionOption.OpenIfExists) Dim myFile As StorageFile = Await mySubFolder.CreateFileAsync(DateTime.Now.ToString("yyyy年MM月dd日HH時mm分ss秒") & ".png") saveImageFileName = DateTime.Now.ToString("yyyy年MM月dd日HH時mm分ss秒") & ".png" Dim myImageEncodingProperty As New ImageEncodingProperties myImageEncodingProperty.Subtype = "png" myImageEncodingProperty.Width = 640 myImageEncodingProperty.Height = 480 ‘ このアプリの肝、Webカメラからの画像を保存する Await myMediaCapture.CapturePhotoToStorageFileAsync(myImageEncodingProperty, myFile) myPictureFiles = Await mySubFolder.GetFilesAsync() Index = myPictureFiles.Count saveBmp = New BitmapImage saveBmp.SetSource(Await myPictureFiles(Index - 1).OpenReadAsync) Dim myImage As New Image With myImage .Width = 640 .Height = 480 .Source = saveBmp End With Dim myStackPanel As New StackPanel Dim recordButton As New Button With recordButton .Content = "録音開始" .Tag = no.ToString End With myStackPanel.Children.Add(myImage) myStackPanel.Children.Add(recordButton) PhotoArea.Children.Add(myStackPanel) AddHandler recordButton.Click, Async Sub(delSender As Object, delArgs As RoutedEventArgs) Dim wavFolder = KnownFolders.PicturesLibrary Dim myWavSubFolder = Await wavFolder.CreateFolderAsync("ImageRecordSoundFile", CreationCollisionOption.OpenIfExists) Dim delDbFile = Await myWavSubFolder.GetFilesAsync For Each result In delDbFile If result.Path.Contains("Thumbs.db") Then Await result.DeleteAsync End If Next Select Case recordButton.Content.ToString Case "録音開始" recordTextBlock.Visibility = Xaml.Visibility.Visible Dim recordFile = Await myWavSubFolder.CreateFileAsync(Path.GetFileNameWithoutExtension(saveImageFileName) & ".mp4", CreationCollisionOption.OpenIfExists) ‘ このアプリの肝、音声ファイルを保存する。 Dim saveRecordeFile As StorageFile = recordFile Await myRecordMediaCapture.StartRecordToStorageFileAsync(myProfile, saveRecordeFile) recordButton.Content = "録音終了" ProgressRing1.IsActive = True ProgressRing1.IsEnabled = True Exit Select Case "録音終了" Await myRecordMediaCapture.StopRecordAsync recordTextBlock.Visibility = Xaml.Visibility.Collapsed ProgressRing1.IsActive = False ProgressRing1.IsEnabled = False PhotoArea.Children.Clear() Exit Select End Select End Sub no += 1 ichiranButton.IsEnabled = True End Sub
以降、上記コードの中身を詳細に見ていこう。
まず、非同期処理で行われるためメソッドの先頭にAsyncを追加している。
次に、Canvas内を一度クリアして、MediaElement1を再生する。つまり、シャッター音が鳴る動作だ。
ピクチャライブラリーにアクセスし、CreateFolderAsyncメソッドで、ピクチャフォルダー内に「ImageVoiceRecord」というサブフォルダーを作成する。その際、CreationCollisionOption.OpenIfExistsと指定しておくと、同名フォルダーやファイルがある場合は、そのフォルダーやファイル名を返し、ない場合は新規に作成してくれる。
CreateFileAsyncメソッドで現在の「年月日時間分秒.png」ファイルを作成し、ファイルを表すメンバー変数「myFile」で参照しておく。メンバー変数「saveImageFileName」に、このpngファイル名を格納しておく。
イメージストリームの書式を表す新しい、ImageEncodingPropertiesクラスのインスタンス、myImageEncodingPropertyオブジェクトを作成する。書式のサブタイプを表すSubtypeプロパティに「png」を指定し、Widthに「640」、Heightに「480」と指定する。
CapturePhotoToStorageFileAsyncメソッドで、ストレージファイルにフォトをキャプチャする。書式は以下の通りだ。
CapturePhotoToStorageFileAsync(ImageEncodingProperties,IStorageFile)
コレクション変数myPictureFilesにGetFilesAsyncメソッドで、「ImageVoiceRecord」フォルダー内の画像ファイルを取得して格納する。
コレクション変数myPictureFilesが格納しているファイルの個数を、Countプロパティで取得して、メンバー変数Indexに格納する。
新しいBitmapImageクラスのインスタンスsaveBmpを作成する。SetSourceメソッドに、「Await myPictureFiles(Index - 1).OpenReadAsync」と指定して、コレクション変数内のIndexに対応するファイルをOpenReadAsyncメソッドで開き、ソースイメージに指定する。
Indexを-1しているのは、コレクション変数「myPictureFiles」が格納しているファイルのインデックスが0から始まるためだ。
新しいImageのインスタンスmyImageオブジェクトを作成し、Widthに「640」、Heightに「480」と指定し、SourceプロパティにSaveBmpオブジェクトを指定する。
StackPanelの新しいインスタンスmyStackPanelオブジェクトを作成する。
Buttonの新しいインスタンスrecordButtonを作成する。Contentプロパティに「録音開始」と指定し、Tagプロパティに文字列にキャストした、1ずつ増加するメンバー変数「no」の値を指定する。
myStackPanelオブジェクトに、myImageとrecordButtonオブジェクトを追加する。「PhotopArea」という名前を持つ、CanvasにAddメソッドでmyStackPanelオブジェクトを追加する。画像に、「録音開始」ボタンが付加して表示される。
AddHandlerステートメントで、recordButtonがクリックされた時のイベントハンドラを追加する。イベントハンドラ内では、以下の処理を行う。
ピクチャライブラリー内の「ImageRecordSoundFile」フォルダーにアクセスする。このフォルダー内のファイルをGetFilesAsyncメソッドで取得し、delDbFileで参照する。このフォルダー内に「Thumbs.db」というファイルがあれば削除する。
Select Case文を使って、recordButtonのContentプロパティの値で条件分岐を行う。
ボタンの文字が「録音開始」だった場合には、以下の処理を行う。「録音中……」という文字を表示する。CreateFileAsyncメソッドで、メンバー変数「saveImageFileName」の格納しているファイル名から、指定したファイル名のパス文字列を、拡張子を付けずに取得する。
文字列".mp4"と連結してMP4ファイルを作成し、変数recordFileで参照しておく。ファイルを表す変数「saveRecordFile」をrecordFileで初期化しておく。
StartRecordToStorageFileAsyncメソッドで、ストレージファイルへ非同期的な記録を開始する。書式は下記の通りだ。
MediaCapture. StartRecordToStorageFileAsync(記録用のエンコーディング プロファイル,イメージを保存するストレージ ファイル)
recordButtonの表面の文字を「録音終了」に変更し、ProgressRing1を動作させる。録音をしている間はプログレスリングが回る。
ボタンの文字が「録音終了」で、このボタンをタップした場合は以下の処理を行う。StopRecordAsyncメソッドでは、「録音中……」の文字を消し、ProgressRing1の動作を停止する。
「PhotoArea」という名前のCanvas内をクリアする。表示されていた画像も消えてしまう。
メンバー変数「no」の値を1ずつ増加し、「一覧」アイコンの使用を可能にする。
Copyright © ITmedia, Inc. All Rights Reserved.