Using the WinRT Media APIs to encode audio in Desktop C# apps


Back to index Matthieu Maitre

The Windows Runtime (WinRT) provides the MediaStreamSource and MediaTranscoder classes to encode audio/video streams in Universal Phone/Windows Store apps. Those classes are not limited to Store apps though: they can also be used in Desktop apps (command line, WPF, etc.) via a few tricks.

Enabling WinRT APIs in Desktop C# apps

The first trick is to enable Windows Runtime support in Desktop C# projects. Toward that end, open the .csproj file in your favorite text editor and:

<TargetPlatformVersion>8.1</TargetPlatformVersion>
<TargetFrameworkVersion>v4.5.1</TargetFrameworkVersion>
<Reference Include="Windows" />
<Reference Include="System.Runtime" />
<Reference Include="System.Runtime.InteropServices.WindowsRuntime" />
<Reference Include="System.Runtime.WindowsRuntime" />

Then save, go to Visual Studio, and reload the project (Visual Studio automatically prompts for that).

Accessing known folders

The second trick is to work around WinRT APIs which are tied to Store apps. For instance most of StorageFile and StorageFolder work in Desktop apps but KnownFolders has issues. The work around is to get paths to known folders using Environment.GetFolderPath() first and then pass those paths to StorageFolder.GetFolderFromPathAsync() to open a StorageFolder:

StorageFolder musicFolder = await StorageFolder.GetFolderFromPathAsync(
    Environment.GetFolderPath(Environment.SpecialFolder.MyMusic)
    );

Encoding audio data

Besides that, the code to encode audio is the same in Desktop apps as in Store apps. First create a MediaStreamSource specifying the input audio format via AudioEncodingProperties and generating audio data in the SampleRequested event handler:

var source = new MediaStreamSource(
    new AudioStreamDescriptor(
        generator.EncodingProperties
        )
    );

source.SampleRequested += (MediaStreamSource sender, MediaStreamSourceSampleRequestedEventArgs args) =>
{
    args.Request.Sample = generator.GenerateSample();
};

Then create a MediaTranscoder, passing the media source, a destination stream, and a destination encoding profile (say M4A):

var transcoder = new MediaTranscoder();
var result = await transcoder.PrepareMediaStreamSourceTranscodeAsync(
    source,
    destination,
    MediaEncodingProfile.CreateM4a(AudioEncodingQuality.Medium)
    );
await result.TranscodeAsync();

Source code

For more details, see the full code sample here.