如何转换.wav格式的语音语音并使用它

时间:2017-09-27 12:43:39

标签: c# facebook speech-recognition botframework speech-to-text

我正在开发一个机器人,它将接收语音(来自Facebook频道),并将在.wav中进行转换。

我正在使用以下示例:How can a bot receive a voice file from Facebook Messenger (MP4) and convert it to a format that is recognized by speech engines like Bing or Google?

我觉得转换过程中遇到了问题。

这是我的代码:

messagescontroller.cs:

namespace SpeechToText.Controllers
{
using System;
using System.Linq;
using System.Net;
using System.Net.Http;
using System.Threading.Tasks;
using System.Web.Http;
using Microsoft.Bot.Connector;
using Services;
using System.Web.Configuration;
using System.IO;

[BotAuthentication]
public class MessagesController : ApiController
{
    private readonly MicrosoftCognitiveSpeechService speechService = new MicrosoftCognitiveSpeechService();

    /// <summary>
    /// POST: api/Messages
    /// Receive a message from a user and reply to it
    /// </summary>
    public async Task<HttpResponseMessage> Post([FromBody]Activity activity)
    {
        if (activity.Type == ActivityTypes.Message)
        {
            var connector = new ConnectorClient(new Uri(activity.ServiceUrl));

            string message = string.Empty;
            IncomingFacebookVoiceMessage voice = null;

            try
            {
                voice = new IncomingFacebookVoiceMessage(activity);
                //await SendReply(activity, "The type of your voice file is " + voice.ContentType);
            }
            catch
            {
                message = "Send me a voice message instead!"; // no voice file found
            }

            try
            {
                if (voice != null)
                {
                    //Download original MP4 voice message
                    voice.DownloadFile();
                    var mp4 = voice.GetLocalPathAndFileName();

                    //Convert MP4 to WAV
                    //  var wavFolder = Utils.GetHomeFolder() + WebConfigurationManager.AppSettings["WAVFilesFolder"];

                    var wavFolder = "C:" + @"\" + "Teste" ;
                    var converter = new AudioFileFormatConverter(mp4, wavFolder);
                    var wav = converter.ConvertMP4ToWAV();

                    //Convert .WAV file to text
                    var bing = new MicrosoftCognitiveSpeechService(); //gets the path + filename
                                                                      // var text = await bing.GetTextFromAudioAsync(wav); //takes path+filename to WAV file, returns text

                    // convert string to stream
                    byte[] data = File.ReadAllBytes(wav);
                    //byte[] byteArray = Encoding.ASCII.GetBytes(contents);
                    MemoryStream stream = new MemoryStream(data);

                    var text = await this.speechService.GetTextFromAudioAsync(stream);

                    if (string.IsNullOrWhiteSpace(text))
                    {
                        message = "Looks like you didn't say anything.";
                    }
                    else
                    {
                        message = text;
                    }

                    //Clean up files from disk
                    voice.RemoveFromDisk();
                    converter.RemoveTargetFileFromDisk();
                }
            }
            catch (Exception ex)
            {
                message = "Woah! " + ex.Message.Trim().Trim('.') + "!";
            }

            Activity reply = activity.CreateReply(message);
            await connector.Conversations.ReplyToActivityAsync(reply);
        }
        else
        {
            await this.HandleSystemMessage(activity);
        }

        return Request.CreateResponse(HttpStatusCode.OK);
    }



    /// <summary>
    /// Gets the JwT token of the bot. 
    /// </summary>
    /// <param name="connector"></param>
    /// <returns>JwT token of the bot</returns>


    /// <summary>
    /// Handles the system activity.
    /// </summary>
    /// <param name="activity">The activity.</param>
    /// <returns>Activity</returns>
    private async Task<Activity> HandleSystemMessage(Activity activity)
    {
        switch (activity.Type)
        {
            case ActivityTypes.DeleteUserData:
                // Implement user deletion here
                // If we handle user deletion, return a real message
                break;
            case ActivityTypes.ConversationUpdate:
                // Greet the user the first time the bot is added to a conversation.
                if (activity.MembersAdded.Any(m => m.Id == activity.Recipient.Id))
                {
                    var connector = new ConnectorClient(new Uri(activity.ServiceUrl));

                    var response = activity.CreateReply();
                    response.Text = "Hi! I am SpeechToText Bot. I can understand the content of any audio and convert it to text. Try sending me a wav file.";

                    await connector.Conversations.ReplyToActivityAsync(response);
                }

                break;
            case ActivityTypes.ContactRelationUpdate:
                // Handle add/remove from contact lists
                break;
            case ActivityTypes.Typing:
                // Handle knowing that the user is typing
                break;
            case ActivityTypes.Ping:
                break;
        }

        return null;
    }
    }
    }

-------------------- IncomingFacebookVoiceMessage.cs

using Microsoft.Bot.Connector;
using System;
  using System.Collections.Generic;
  using System.IO;
 using System.Linq;
  using System.Net;
 using System.Web;
   using System.Web.Configuration;


 namespace SpeechToText
{
/// <summary>
/// Represents an incoming voice message from facebook messenger, 
/// where the voice data is in an MP4 file (the message contains a link to 
 download it).
/// </summary>
public class IncomingFacebookVoiceMessage
{
    #region Properties
    /// <summary>
    /// URL of the MP4 file sent by user and stored on facebook's servers.
    /// </summary>
    public Uri MP4FileUrl { get; private set; }

    /// <summary>
    /// Local filename of the MP4 file after it has been downloaded from Facebook.
    /// </summary>
    private string MP4LocalFileName { get; set; }

    /// <summary>
    /// Path to the folder on local disk containing the downloaded voice messages from Facebook.
    /// This is configured in Web.config using the FacebookDownloadedVoiceMessagesFolder key.
    /// The path in the Web.config will be relative to the site's root folder.
    /// </summary>
    public string VoiceMessageFolder { get; private set; }

    /// <summary>
    /// Content-type of the attachment (for debugging - it's not always MP4).
    /// </summary>
    public string ContentType { get; private set; }
    #endregion

    #region Constructors
    /// <summary>
    /// Constructor that uses an MP4 file link that is 
    /// received in activity.Attachments by bot framework.
    /// </summary>
    /// <param name="MP4FileUrl">URL of the MP4 file sent by user and stored on facebook's servers.</param>
    public IncomingFacebookVoiceMessage(string MP4FileUrl)
    {
        if (string.IsNullOrWhiteSpace(MP4FileUrl))
        {
            throw new Exception("The MP4 file URL was empty.");
        }

        this.MP4FileUrl = new Uri(MP4FileUrl);
        this.VoiceMessageFolder = GetVoiceMessagesFolderFromWebConfig();
    }

    /// <summary>
    /// A shortcut constructor that extracts the URL of the MP4 voice message file
    /// from the Activity object received by the controller in the Bot Framework.
    /// </summary>
    /// <param name="activity">The Activity object that contains an attachment of type video/mp4. If no attachment, throws an exception.</param>
    public IncomingFacebookVoiceMessage(IMessageActivity activity)
    {
        var mp4Attachment = activity.Attachments?.FirstOrDefault(a => a.ContentType.Equals("video/mp4") || a.ContentType.Contains("audio") || a.ContentType.Contains("video"));
        if (mp4Attachment == null)
        {
            throw new Exception("The message didn't have a voice attachment.");
        }
        else
        {
            this.MP4FileUrl = new Uri(mp4Attachment.ContentUrl);
            this.VoiceMessageFolder = GetVoiceMessagesFolderFromWebConfig();
            this.ContentType = mp4Attachment.ContentType; //for debugging. Different devices send different content-types, e.g. audio/aac and video/mp4
        }
    }
    #endregion

    #region Public methods
    /// <summary>
    /// Downloads the MP4 file containing the voice message from Facebook.
    /// </summary>
    /// <returns>The filename (without path) of the MP4 file stored on local disk.</returns>
    public string DownloadFile()
    {
        var filename = GetRandomFileName();
        var filenameWithPath = VoiceMessageFolder + @"\" + filename;

        //if folder doesn't exist, create it
        if (!Directory.Exists(VoiceMessageFolder))
        {
            Directory.CreateDirectory(VoiceMessageFolder);
        }

        using (var client = new WebClient())
        {
            client.DownloadFile(this.MP4FileUrl, filenameWithPath);
        }

        MP4LocalFileName = filename;

        return filename;
    }

    /// <summary>
    /// Removes the downloaded MP4 file from the local disk to clean up space.
    /// </summary>
    /// <returns>True if successfully removed, false otherwise.</returns>
    public bool RemoveFromDisk()
    {
        try
        {
            File.Delete(GetLocalPathAndFileName());
            return true;
        }
        catch
        {
            return false;
        }
    }

    /// <summary>
    /// Returns the full local path and filename to the downloaded MP4 voice message.
    /// </summary>
    /// <returns>E.g. D:\home\site\wwwroot\abc.mp4</returns>
    public string GetLocalPathAndFileName()
    {
        if (string.IsNullOrWhiteSpace(MP4LocalFileName))
        {
            throw new Exception("The voice message has not been downloaded yet.");
        }

        return VoiceMessageFolder + @"\" + MP4LocalFileName;
    }

    #endregion

    #region Private methods
    /// <summary>
    /// Reads Web.config and returns the path to the folder which will store downloaded messages.
    /// The folder in the config must be relative to the site's root.
    /// </summary>
    /// <returns>Full path to the folder that will be used to store MP4 voice messages.</returns>
    private string GetVoiceMessagesFolderFromWebConfig()
    {
        //return Utils.GetHomeFolder() + WebConfigurationManager.AppSettings["FacebookDownloadedVoiceMessagesFolder"];
        return "C:" + @"\" + "Teste" ;
    }

    /// <summary>
    /// Generates a random filename using a new GUID.
    /// </summary>
    /// <returns>A random file name in the format "msg-GUID.mp4".</returns>
    private string GetRandomFileName()
    {
        return "msg-" + Guid.NewGuid() + ".mp4";
    }
    #endregion
   }
   }

--------------- AudioFileFormatConverter.cs

 using MediaToolkit;
 using MediaToolkit.Model;
 using System;
   using System.IO;
 using System.Web.Configuration;

  namespace SpeechToText
     {
/// <summary>
/// Converts audio files between various formats using the open-source 
   FFMPEG software.
/// </summary>
public class AudioFileFormatConverter
{
    #region Properties
    /// <summary>
    /// Path + filename to the source file.
    /// </summary>
    public string SourceFileNameAndPath { get; private set; }

    /// <summary>
    /// Path + filename to the file which is the result of the conversion.
    /// </summary>
    public string ConvertedFileNameAndPath { get; private set; }

    /// <summary>
    /// The folder where the converted files will be stored.
    /// </summary>
    public string TargetPath { get; private set; }

    #endregion

    #region Constructors
    /// <summary>
    /// Default constructor. 
    /// </summary>
    /// <param name="sourceFileNameAndPath">Filename and path to the source 
      file.</param>
    /// <param name="targetPath">The folder where the converted files will 
      be stored.</param>
    public AudioFileFormatConverter(string sourceFileNameAndPath, string 
    targetPath)
    {
        if (string.IsNullOrWhiteSpace(sourceFileNameAndPath))
        {
            throw new Exception("Empty source filename.");
        }
        else if (string.IsNullOrWhiteSpace(targetPath))
        {
            throw new Exception("Empty target path.");
        }
        else
        {
            this.SourceFileNameAndPath = sourceFileNameAndPath;
            this.TargetPath = targetPath;

            //create folder if it's not there
            if (!Directory.Exists(TargetPath))
            {
                Directory.CreateDirectory(TargetPath);
            }
        }
    }
    #endregion

    #region Public methods
    /// <summary>
    /// Converts a source MP4 file to a target WAV file and returns the path 
     and filename of the converted file.
    /// </summary>
    /// <returns>The path and filename of the converted file.</returns>
    public string ConvertMP4ToWAV()
    {
        ConvertedFileNameAndPath = TargetPath + @"\" + 
         Path.GetFileNameWithoutExtension(SourceFileNameAndPath) + ".wav"; 
       //use the same 
   file name as original, but different folder and extension

        var inputFile = new MediaFile { Filename = SourceFileNameAndPath };
        var outputFile = new MediaFile { Filename = ConvertedFileNameAndPath 
       };
        using (var engine = new Engine(GetFFMPEGBinaryPath()))
        {
            engine.Convert(inputFile, outputFile);
        }

        return ConvertedFileNameAndPath;
    }

    /// <summary>
    /// Removes the converted file from disk to free up space. 
    /// Doesn't remove the source file.
    /// </summary>
    /// <returns>True if file deleted successfully, false if cannot delete, 
    exception if filename is empty.</returns>
    public bool RemoveTargetFileFromDisk()
    {
        if (string.IsNullOrWhiteSpace(ConvertedFileNameAndPath))
        {
            throw new Exception("The file has not been converted yet, so it cannot be deleted.");
        }

        try
        {
            File.Delete(ConvertedFileNameAndPath);
            return true;
        }
        catch
        {
            return false;
        }
    }
    #endregion

    #region Private methods
    /// <summary>
    /// Reads the config to determine the location of ffmpeg.exe.
    /// </summary>
    /// <returns>The full path and filename to the ffmpeg.exe program.
   </returns>
    public string GetFFMPEGBinaryPath()
    {
        // return Utils.GetHomeFolder() + 
     WebConfigurationManager.AppSettings["FFMPEGBinaryLocation"];
        return "D:" + @"\" + "Teste";
    }
    #endregion
   }
   }

这是我的输出消息:

enter image description here

你能帮我解决一下这个问题......我应该把音频寄存器存放在facebook messenger中吗?

1 个答案:

答案 0 :(得分:0)

我认为你缺少的是GetFFMPEGBinaryPath()方法中的ffmpeg.exe。一旦我将它添加到路径的末尾,您可以按预期运行代码。

public string GetFFMPEGBinaryPath()
{
     return "D:" + @"\Teste\ffmpeg-20170921-183fd30-win64-static\bin\ffmpeg.exe";
}