2017-09-27 216 views
1

我正在開發一個機器人,它將接收語音(從Facebook頻道),並將其轉換爲.wav。如何轉換格式.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的信使音頻寄存器?

+0

你有沒有回顧:https://github.com/catcher-in-the-try/Facebook-Messenger-Voice-Message-Converter –

+0

的[如何轉換.wav文件爲.mp3可能的複製格式在botframework](https://stackoverflow.com/questions/46492024/how-to-convert-a-wav-file-to-mp3-format-in-botframework) –

+0

這可能是更好的更改' GetRandomFileName()'並將'GetUniqueFileName()'稱爲'NewGuid()'不會產生隨機值,它會產生唯一的值。 – Enigmativity

回答

0

我認爲你所缺少的是GetFMPEGBinaryPath()方法中的ffmpeg.exe。一旦我將其添加到路徑的末尾,代碼就具有預期的功能。

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