読者です 読者をやめる 読者になる 読者になる

かずきのBlog@hatena

日本マイクロソフトに勤めています。XAML + C#の組み合わせをメインに、たまにASP.NETやJavaなどの.NET系以外のことも書いています。掲載内容は個人の見解であり、所属する企業を代表するものではありません。

UWPでマイクから録音したい

UWP

MediaCaptureクラスを使ってやることが出来ます。

まず、MediaCaptureクラスの初期化処理が必要になります。OnNavigatedToあたりに書くといいでしょう。

private MediaCapture MediaCapture { get; set; }
protected override async void OnNavigatedTo(NavigationEventArgs e)
{
    base.OnNavigatedTo(e);

    this.MediaCapture = new MediaCapture();
    var settings = new MediaCaptureInitializationSettings
    {
        StreamingCaptureMode = StreamingCaptureMode.Audio
    };

    await this.MediaCapture.InitializeAsync(settings);
}

次に録音処理です。Streamに吐き出したり直接ファイルに吐き出したりできます。ここではいったんメモリに吐き出すようにしました。手順としては、StartRecordToStreamAsyncメソッドを呼び出すだけです。引数で、何形式で録音するのかということと、出力先を指定します。

private InMemoryRandomAccessStream Stream { get; set; }


// 録音
this.Stream = new InMemoryRandomAccessStream();
await this.MediaCapture.StartRecordToStreamAsync(
    MediaEncodingProfile.CreateMp3(AudioEncodingQuality.Medium),
    this.Stream);

録音を停止するにはStopRecordAsyncを呼び出すだけです。後は、ファイルに保存するなりできます。ここではFileSavePickerで選択したファイルに保存するようにしています。

await this.MediaCapture.StopRecordAsync();

var picker = new FileSavePicker();
picker.FileTypeChoices.Add("mp3", new List<string> { ".mp3" });
var file = await picker.PickSaveFileAsync();
if (file != null)
{
    using (var os = await file.OpenStreamForWriteAsync())
    {
        this.Stream.Seek(0);
        await this.Stream.AsStreamForRead().CopyToAsync(os);
        await os.FlushAsync();
    }
}
this.Stream.Dispose();
this.Stream = null;

最後に大事なことなのですがPackage.appxmanifestの機能のところで「マイク」にチェックを入れてマイクへのアクセスを行えるようにします。

コード全体

コード全体です。画面にボタンを1つおいて、それのクリックイベントハンドラに処理を書いています。

<Page x:Class="App46.MainPage"
      xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
      xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
      xmlns:local="using:App46"
      xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
      xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
      mc:Ignorable="d">

    <Grid Background="{ThemeResource ApplicationPageBackgroundThemeBrush}">
        <Button Content="録音/停止"
                Click="Button_Click" />
    </Grid>
</Page>
using System;
using System.Collections.Generic;
using System.IO;
using Windows.Media.Capture;
using Windows.Media.MediaProperties;
using Windows.Storage.Pickers;
using Windows.Storage.Streams;
using Windows.UI.Xaml;
using Windows.UI.Xaml.Controls;
using Windows.UI.Xaml.Navigation;

namespace App46
{
    public sealed partial class MainPage : Page
    {
        private InMemoryRandomAccessStream Stream { get; set; }
        private MediaCapture MediaCapture { get; set; }
        public MainPage()
        {
            this.InitializeComponent();
        }

        protected override async void OnNavigatedTo(NavigationEventArgs e)
        {
            base.OnNavigatedTo(e);

            this.MediaCapture = new MediaCapture();
            var settings = new MediaCaptureInitializationSettings
            {
                StreamingCaptureMode = StreamingCaptureMode.Audio
            };

            await this.MediaCapture.InitializeAsync(settings);
        }

        private async void Button_Click(object sender, RoutedEventArgs e)
        {
            if (this.Stream == null)
            {
                this.Stream = new InMemoryRandomAccessStream();
                await this.MediaCapture.StartRecordToStreamAsync(
                    MediaEncodingProfile.CreateMp3(AudioEncodingQuality.Medium),
                    this.Stream);
            }
            else
            {
                await this.MediaCapture.StopRecordAsync();

                var picker = new FileSavePicker();
                picker.FileTypeChoices.Add("mp3", new List<string> { ".mp3" });
                var file = await picker.PickSaveFileAsync();
                if (file != null)
                {
                    using (var os = await file.OpenStreamForWriteAsync())
                    {
                        this.Stream.Seek(0);
                        await this.Stream.AsStreamForRead().CopyToAsync(os);
                        await os.FlushAsync();
                    }
                }
                this.Stream.Dispose();
                this.Stream = null;
            }
        }
    }
}