【问题标题】:Recording/Capture Currently Playing Audio录制/捕获当前播放的音频
【发布时间】:2017-05-27 16:40:39
【问题描述】:

我想在 UWP 或 Windows Phone 8.1 中捕获/记录当前播放的音频,“MEE dj”UWP 应用程序在其应用程序中完成相同的操作,该应用程序能够捕获应用程序中当前正在播放的音频。 请知道的人分享你的答案。

【问题讨论】:

    标签: c# windows-phone-8.1 uwp audio-capture


    【解决方案1】:

    如何设置输入节点播放音乐而不是麦克风

    Windows.Media.Audio namespace 包含AudioDeviceInputNode,AudioDeviceOutputNode,AudioFileInputNode,AudioFileOutputNode 等等。输入的麦克风是AudioDeviceInputNode,但播放音乐文件需要使用AudioFileInputNode

    好的,但是我怎样才能捕获该音频并将其保存到存储中

    如上所述,为了保存到存储,我们需要使用AudioFileOutputNode。这是一个简单的演示,您可以加载一个文件进行录制,并从存储中选择一个文件来保存录制结果。代码如下:

    XAML 代码

    <StackPanel Background="{ThemeResource ApplicationPageBackgroundThemeBrush}" Padding="50">
        <TextBlock x:Name="txtresult" ></TextBlock>
        <Button x:Name="fileButton" Content="Load audio File for recording" Click="File_Click" MinWidth="120" MinHeight="45" Margin="0,20,0,0"/>
        <Button x:Name="OutpuyfileButton" Content="Load output File for save the recording result" Click="OutpuyfileButton_Click" MinWidth="120" MinHeight="45" Margin="0,20,0,0"/>
        <Button x:Name="graphButton" Content="Start playing" Click="Graph_Click" MinWidth="120" MinHeight="45" Margin="0,50,0,20"/>
        <Button x:Name="graphrecord" Content="Begin recording" Click="graphrecord_Click" ></Button>
    </StackPanel>
    

    后面的代码

      private AudioFileInputNode fileInput;
      private AudioFileOutputNode fileOutputNode;
      private AudioDeviceOutputNode deviceOutput;
      private AudioGraph graph;
    
      StorageFile outputfile;
    
      public MainPage()
      {
          this.InitializeComponent();
      }
      protected override async void OnNavigatedTo(NavigationEventArgs e)
      {
          await CreateAudioGraph();
      }
      private async Task CreateAudioGraph()
      {
          // Create an AudioGraph with default settings
          AudioGraphSettings settings = new AudioGraphSettings(AudioRenderCategory.Media);
          CreateAudioGraphResult result = await AudioGraph.CreateAsync(settings);
          if (result.Status != AudioGraphCreationStatus.Success)
          {
              // Cannot create graph
              await new MessageDialog(String.Format("AudioGraph Creation Error because {0}", result.Status.ToString())).ShowAsync();
              return;
          }
          graph = result.Graph;
          // Create a device output node
          CreateAudioDeviceOutputNodeResult deviceOutputNodeResult = await graph.CreateDeviceOutputNodeAsync();
          if (deviceOutputNodeResult.Status != AudioDeviceNodeCreationStatus.Success)
          {
              // Cannot create device output node
            txtresult.Text+="\n"+ String.Format("Device Output unavailable because {0}", deviceOutputNodeResult.Status.ToString());
              return;
          }
          deviceOutput = deviceOutputNodeResult.DeviceOutputNode;
          txtresult.Text += "\n" + "Device Output Node successfully created";
      }
      private async void File_Click(object sender, RoutedEventArgs e)
      {
          // If another file is already loaded into the FileInput node
          if (fileInput != null)
          {
              fileInput.Dispose();
          }
          FileOpenPicker filePicker = new FileOpenPicker();
          filePicker.SuggestedStartLocation = PickerLocationId.MusicLibrary;
          filePicker.FileTypeFilter.Add(".mp3");
          filePicker.FileTypeFilter.Add(".wav");
          filePicker.FileTypeFilter.Add(".wma");
          filePicker.FileTypeFilter.Add(".m4a");
          filePicker.ViewMode = PickerViewMode.Thumbnail;
          StorageFile file = await filePicker.PickSingleFileAsync();
          // File can be null if cancel is hit in the file picker
          if (file == null)
          {
              return;
          }
          CreateAudioFileInputNodeResult fileInputResult = await graph.CreateFileInputNodeAsync(file);
          if (AudioFileNodeCreationStatus.Success != fileInputResult.Status)
          {
              // Cannot read input file
              await new MessageDialog(String.Format("Cannot read input file because {0}", fileInputResult.Status.ToString())).ShowAsync();
              return;
          }
    
          fileInput = fileInputResult.FileInputNode;
          txtresult.Text += "\n" + "File load successfully,input nodes created";
      }
    
      private void Graph_Click(object sender, RoutedEventArgs e)
      {
          if (graphButton.Content.Equals("Start playing"))
          {
              fileInput.AddOutgoingConnection(deviceOutput);
              graph.Start();            
              graphButton.IsEnabled = false;
          }
      }
    
      private async void OutpuyfileButton_Click(object sender, RoutedEventArgs e)
      {
          FileSavePicker saveFilePicker = new FileSavePicker();
          saveFilePicker.FileTypeChoices.Add("Pulse Code Modulation", new List<string>() { ".wav" });
          saveFilePicker.FileTypeChoices.Add("Windows Media Audio", new List<string>() { ".wma" });
          saveFilePicker.FileTypeChoices.Add("MPEG Audio Layer-3", new List<string>() { ".mp3" });
          saveFilePicker.SuggestedFileName = "New Audio Track";
          outputfile = await saveFilePicker.PickSaveFileAsync();
          // File can be null if cancel is hit in the file picker
          if (outputfile == null)
          {
              return;
          }
    
          txtresult.Text +="\n"+ String.Format("Recording to {0}", outputfile.Name.ToString());
      }
      private MediaEncodingProfile CreateMediaEncodingProfile(StorageFile file)
      {
          switch (file.FileType.ToString().ToLowerInvariant())
          {
              case ".wma":
                  return MediaEncodingProfile.CreateWma(AudioEncodingQuality.High);
              case ".mp3":
                  return MediaEncodingProfile.CreateMp3(AudioEncodingQuality.High);
              case ".wav":
                  return MediaEncodingProfile.CreateWav(AudioEncodingQuality.High);
              default:
                  throw new ArgumentException();
          }
      }
    
      private async void graphrecord_Click(object sender, RoutedEventArgs e)
      {
          if (graphrecord.Content.Equals("Begin recording"))
          {
              MediaEncodingProfile fileProfile = CreateMediaEncodingProfile(outputfile);
              CreateAudioFileOutputNodeResult fileOutputNodeResult = await graph.CreateFileOutputNodeAsync(outputfile, fileProfile);
              if (fileOutputNodeResult.Status != AudioFileNodeCreationStatus.Success)
              {
                  // FileOutputNode creation failed
                  await new MessageDialog(String.Format("Cannot create output file because {0}", fileOutputNodeResult.Status.ToString())).ShowAsync();
                  return;
              }
              fileOutputNode = fileOutputNodeResult.FileOutputNode;
              fileInput.AddOutgoingConnection(fileOutputNode);
              graphrecord.Content = "Stop recording";
          }
          else
          {
              graph.Stop();
              TranscodeFailureReason finalizeResult = await fileOutputNode.FinalizeAsync();
              if (finalizeResult != TranscodeFailureReason.None)
              {
                  // Finalization of file failed. Check result code to see why
                  await new MessageDialog(String.Format("Finalization of file failed because {0}", finalizeResult.ToString())).ShowAsync();
                  return;
              }
              txtresult.Text += "\n" + "Recording completed";
              graphrecord.IsEnabled = false;
          }
      }
    

    其他复杂的功能,还是参考官方示例吧。

    【讨论】:

      【解决方案2】:

      您可以使用 Windows.Media.Audio 命名空间中的 API 为音频路由、混音和处理场景创建音频图。音频图的制作方法请参考this article

      音频图是一组相互连接的音频节点。您要录制的音频文件提供“音频输入节点”,“音频输出节点”是图形处理音频的目的地,音频可以从图形路由到目标音频文件。在“MeeDJ”windows store 应用程序中,它可以将两种音频混合并录制为一个。在这种情况下,我们可以使用“子混合节点”,从一个或多个节点获取音频并将它们组合成一个输出。

      而对于开始和停止录制,我们可以尝试使用Starting and stopping audio graph nodes 来实现。你也可以像“MeeDJ”一样尝试Adding audio effects

      更多功能和示例代码请参考official sample

      【讨论】:

      • 好的,但我怎样才能捕获该音频并将其保存到存储中
      • 音频创建示例中的所有给定场景都是通过麦克风录制工作室而不是播放音频
      • @ShubhamSahu 您找到的用于通过麦克风录制的样本,因为输入节点是麦克风输入。详细阅读方案 1 和文档,你会发现你可以做你想做的事。除了示例仅供参考,它无法提供您想要的相同演示,我也无法为您编写。 API支持你想要的,我已经提供了如何做,但细节需要你做。
      • @ShubhamSahu,scenairo1 提供捕获音频,然后播放。您可以将其保存到存储中而不是播放。如果您甚至不知道如何将文件保存到存储中,请进行研究。如果您仍然无法解决,请告诉我您被阻止的步骤,我会帮助您。
      • @ShubhamSahu,由于答案有点长而且还有其他问题,我回复了一个新答案。请检查一下。
      猜你喜欢
      • 1970-01-01
      • 2018-02-20
      • 2012-02-25
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2023-03-15
      相关资源
      最近更新 更多