Jose Afonso
Jose Afonso

Reputation: 117

How to save SpeechSynthesis audio to a Mp3 file in a UWP application

I'm working on a UWP TTS (Text to Speech) application and I'm having trouble saving speech to a file, preferably in Mp3 format. Does anyone know how to do this? In WPF, I used NAUDIO and NAUDIO.LAME, but unfortunately this does not seem to support UWP. I think I have to use Windows.Media.Transcoding API, but I didn't find any examples of how to do that. I found the code below in an article on MSDN, but it is not correct.

        StorageFile file = await savePicker.PickSaveFileAsync();
        if (file != null)
        {
            try
            {
                SpeechSynthesisStream stream = await WCSVariables.Synthesizer.SynthesizeTextToStreamAsync(rtbText.Text);

                using (var reader = new DataReader(stream))
                {
                    await reader.LoadAsync((uint)stream.Size);
                    IBuffer buffer = reader.ReadBuffer((uint)stream.Size);
                    await FileIO.WriteBufferAsync(file, buffer);
                }


            }
            catch (Exception ex)
            {
                MessageDialog msgdlg = new MessageDialog(ex.Message);
                msgdlg.ShowAsync();
            }

********** UPDATE **********

After adding capabilities and file type associations for TXT and MP3, I was able to save the TXT files in any folder, but the MP3 files do not have the correct format. Files are created but do not play audio.

FileSavePicker savePicker = new FileSavePicker();
        savePicker.SuggestedStartLocation = PickerLocationId.DocumentsLibrary;
        savePicker.FileTypeChoices.Add("Mp3 Audio File", new List<string>() { ".mp3" });
        savePicker.FileTypeChoices.Add("Plain Text", new List<string>() { ".txt" });
        savePicker.SuggestedFileName = "New Document";

        StorageFile file = await savePicker.PickSaveFileAsync();
        if (file != null)
        {
            try
            {
                if (file.FileType == ".txt")
                {
                    await FileIO.WriteTextAsync(file, rtbText.Text);
                }
                else
                {
                    string path = file.Path.Remove(file.Path.IndexOf(file.Name), file.Name.Length);

                    StorageFolder mp3Folder = await StorageFolder.GetFolderFromPathAsync(path);
                    StorageFile mp3File = await mp3Folder.CreateFileAsync(file.Name, CreationCollisionOption.ReplaceExisting);
                    SpeechSynthesisStream stream = await WCSVariables.Synthesizer.SynthesizeTextToStreamAsync(rtbText.Text);

                    using (var reader = new DataReader(stream))
                    {
                        await reader.LoadAsync((uint)stream.Size);
                        IBuffer buffer = reader.ReadBuffer((uint)stream.Size);
                        await FileIO.WriteBufferAsync(mp3File, buffer);
                    }
                }
            } 
            catch (Exception ex)
            {
                MessageDialog msgdlg = new MessageDialog(ex.Message);
                msgdlg.ShowAsync();
            }
        }

Upvotes: 1

Views: 2758

Answers (1)

Faywang - MSFT
Faywang - MSFT

Reputation: 5868

You can first create a .mp3 file and then generate a speech audio stream from a basic text string. After that, write the stream to the file.

StorageFolder folder = KnownFolders.VideosLibrary;
StorageFile file = await folder.CreateFileAsync("MyVideo.mp3",CreationCollisionOption.ReplaceExisting);
if (file != null)
{
    try
    {
        var synth = new Windows.Media.SpeechSynthesis.SpeechSynthesizer();
        SpeechSynthesisStream stream = await synth.SynthesizeTextToStreamAsync("Hello World");

        using (var reader = new DataReader(stream))
        {
            await reader.LoadAsync((uint)stream.Size);
            IBuffer buffer = reader.ReadBuffer((uint)stream.Size);
            await FileIO.WriteBufferAsync(file, buffer);
        }
    }
    catch {}
}

Upvotes: 1

Related Questions