我想在 UWP 或 Windows Phone 8.1 中捕获/记录当前播放的音频,同样的事情是由其应用程序中的“MEE dj”UWP 应用程序完成的,该应用程序能够捕获应用程序中当前正在播放的音频。请知道的人分享您的答案。
2 回答
您可以使用Windows.Media.Audio
命名空间中的 API 为音频路由、混合和处理场景创建音频图。关于如何创建音频图,请参考这篇文章。
音频图是一组相互连接的音频节点。您要录制的音频文件提供“音频输入节点”,“音频输出节点”是图形处理音频的目的地,音频可以从图形路由到目标音频文件。在“MeeDJ”windows store 应用程序中,它可以将两种音频混合并录制为一个。在这种情况下,我们可以使用“子混合节点”,从一个或多个节点获取音频并将它们组合成单个输出。
而对于开始和停止录制,我们可以尝试使用启动和停止音频图节点来实现。您也可以尝试像“MeeDJ”那样添加音频效果。
更多功能和示例代码请参考官方示例。
如何设置输入节点播放音乐而不是麦克风
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;
}
}
对于其他复杂的功能,请仍然参考官方示例。