I want to use StartRecordingToFileAsync function in UWP - c#

I want to record screen audio using AppRecordingManager in UWP.
I found StartRecordingToFileAsync function in AppRecordingManager Class to write audio and video content in UWP.
Here is the official document URL about this function:
https://learn.microsoft.com/en-us/uwp/api/windows.media.apprecording.apprecordingmanager.startrecordingtofileasync#Windows_Media_AppRecording_AppRecordingManager_StartRecordingToFileAsync_Windows_Storage_StorageFile_
Although I try to use this function to record audio, I always keep getting this error:
The request is invalid in the current state. (Exception from HRESULT: 0xC00D36B2)
I can not find solution for StartRecordingToFileAsync.
How can I solve this error?
Here is my c# code giving me this error.
AppRecordingManager manager = AppRecordingManager.GetDefault();
var status = manager.GetStatus();
if (status.CanRecord || status.CanRecordTimeSpan)
{
var myVideo = await Windows.Storage.StorageLibrary.GetLibraryAsync(Windows.Storage.KnownLibraryId.Videos);
StorageFolder projectFolder = await myVideo.SaveFolder.CreateFolderAsync("DataFolder", CreationCollisionOption.OpenIfExists);
var audio = await projectFolder.CreateFileAsync("audio_record.wav", CreationCollisionOption.GenerateUniqueName);
var result = await manager.StartRecordingToFileAsync(audio);
if (result.Succeeded)
{
Debug.WriteLine(result.Succeeded);
}
else
{
Debug.WriteLine(result.ExtendedError.Message);
}
}

I managed to reproduce same error with your code.
But when I changed "audio_record.wav" to "audio_record.mp4" it worked and it saved video to specified location.
Since documentation states that StartRecordingToFileAsync "Writes audio and video content of the current app" it's possible that you can't save just audio using that method.

Related

Showing Images using XF ImagePicker Without Putting Image in Resources

In Xamarin.Forms prerelease they have released a media picker: https://learn.microsoft.com/en-us/xamarin/essentials/media-picker?tabs=android
This is obviously a great addition and the fact that you don't have to use any 3rd party-library is great!
I'm creating an event management app - in the app the user can select an image for the event and be able to see it.
Here is my code:
public async void OnSelectPhotoCommand()
{
var photo = await MediaPicker.PickPhotoAsync();
await LoadPhotoAsync(photo);
}
async Task LoadPhotoAsync(FileResult photo)
{
var newFile = Path.Combine(FileSystem.CacheDirectory, photo.FileName);
using (var stream = await photo.OpenReadAsync())
using (var newStream = File.OpenWrite(newFile)) { await stream.CopyToAsync(newStream); }
ImagePath = newFile;
}
The problem is the image is not showing or appearing whatsoever - I've tried to modify my code and debug it but I am unable to locate the source of the problem.
I want the user to be actually able to see the image - but I am unsure on how to do that using the MediaPicker without putting it in the Android Resources folder?
Thank you,
tommy
From the xamarin essentials documentation be sure to be running it from the UI Thread.
InvokeOnMainThread ( () => {
OnSelectPhotoCommand();
});

Xamarin Form - TaskCanceledException thrown on ScanFilesToFolderAsync

in my UWP application i am working on scan functionality. in this application user can scan the document through scanner by selecting flatbed or auto feeder.Now problem is when i am trying to scan it gives the en exception a Task was canceled.
please help..
thanks in advance. :)
have a great day... :)
private async void Btnscan_Click(object sender, RoutedEventArgs e)
{
FolderPicker folderPicker = new FolderPicker();
folderPicker.SuggestedStartLocation = PickerLocationId.DocumentsLibrary;
folderPicker.FileTypeFilter.Add("*");
StorageFolder folder = await folderPicker.PickSingleFolderAsync();
//set the destination folder name for scan images.
DeviceInformationDisplay selectedScanner = CmbScannerList.SelectedItem as DeviceInformationDisplay; // here i got the selected scanner.
// scanner id is := "\\\\?\\ROOT#IMAGE#0000#{6bdd1fc6-810f-11d0-bec7-08002be2092f}"
ScanToFolder(selectedScanner.id, folder);
}
function Scan To folder
public async void ScanToFolder(string deviceId, StorageFolder folder)
{
try
{
cancellationToken = new CancellationTokenSource();
ImageScanner myScanner = await ImageScanner.FromIdAsync(deviceId);
if (myScanner.IsScanSourceSupported(ImageScannerScanSource.Flatbed))
{
var result = await myScanner.ScanFilesToFolderAsync(ImageScannerScanSource.Flatbed, folder).AsTask(cancellationToken.Token); // through an exception(A Task Was Canceled):(
Utils.DisplayImageAndScanCompleteMessage(result.ScannedFiles, DisplayImage);
}
}
catch (Exception ex)
{
// here i got the exception.
}
}
Updated :
Now i am set the DeviceClass to ALL.
private void StartWatcher()
{
resultCollection.Clear();
DeviceWatcher deviceWatcher;
deviceWatcher = DeviceInformation.CreateWatcher(DeviceClass.All); // set Image scanner to all.
deviceWatcherHelper.StartWatcher(deviceWatcher);
}
After run the project in scanner list i got the all connected devices in which i got my scanner name This : when i am trying to pass this name it gives error in imagescanner System.Exception: 'Exception from HRESULT: 0x80210015' means device not found.
Now i am chnage all to ImageScanner i got nothing in scanner list.
and in scanner HP application i got this name. and IT Scan Well :( in scanner list i don't got this name in my application. :(
on my pc setting -> devices -> scanner and printers i got those name.
Rewriting the resolution of the problem as an answer. I tested the code on my machine where it behaved correctly and argued the problem is most likely a driver issue. This has been confirmed by the OP and reinstall of the driver helped make the scanning work again.

Directory.GetDirectories return empty string inside an async Task operation

I have a UWP application which perform to capture and process images from a camera. This project leverage Microsoft Cognitive Services Face Recognition API and I'm exploring the application's existing functionality for awhile now. My goal is that when the image of a person is identified by the camera (through Face Recognition API service), I want to show the associated image of that person.
With that, the images are captured and stored in a local directory of my machine. I want to retrieve the image file and render it on the screen once the person is identified.
The code below shows the async Task method ProcessCameraCapture
private async Task ProcessCameraCapture(ImageAnalyzer e)
{
if (e == null)
{
this.UpdateUIForNoFacesDetected();
this.isProcessingPhoto = false;
return;
}
DateTime start = DateTime.Now;
await e.DetectFacesAsync();
if (e.DetectedFaces.Any())
{
string names;
await e.IdentifyFacesAsync();
this.greetingTextBlock.Text = this.GetGreettingFromFaces(e, out names);
if (e.IdentifiedPersons.Any())
{
this.greetingTextBlock.Foreground = new SolidColorBrush(Windows.UI.Colors.GreenYellow);
this.greetingSymbol.Foreground = new SolidColorBrush(Windows.UI.Colors.GreenYellow);
this.greetingSymbol.Symbol = Symbol.Comment;
GetSavedFilePhoto(names);
}
else
{
this.greetingTextBlock.Foreground = new SolidColorBrush(Windows.UI.Colors.Yellow);
this.greetingSymbol.Foreground = new SolidColorBrush(Windows.UI.Colors.Yellow);
this.greetingSymbol.Symbol = Symbol.View;
}
}
else
{
this.UpdateUIForNoFacesDetected();
}
TimeSpan latency = DateTime.Now - start;
this.faceLantencyDebugText.Text = string.Format("Face API latency: {0}ms", (int)latency.TotalMilliseconds);
this.isProcessingPhoto = false;
}
In GetSavedFilePhoto, I passed the string names argument once the person is identified.
Code below for the GetSavedFilePhoto method
private void GetSavedFilePhoto(string personName)
{
if (string.IsNullOrWhiteSpace(personName)) return;
var directoryPath = #"D:\PersonImages";
var directories = Directory.GetDirectories(directoryPath);
var filePaths = Directory.GetFiles(directoryPath, "*.jpg", SearchOption.AllDirectories);
}
However, in GetSavedFilePhoto method the variable directories returned an empty string of array when using directoryPath string variable. Directory "D:\PersonImages" is a valid and existing folder in my machine and, it contains subfolders with images inside. I also tried Directory.GetFiles to retrieve the jpg images but still returned an empty string.
I think it should work because I have used Directory class several times but not inside an asyncTask method. Does using async caused the files not returned when using I/O operation?
Sorry for this stupid question, but I really don't understand.
Any help is greatly appreciated.
Using Directory.GetFiles or Directory.GetDirectories method can get the folder/file in the local folder of the Application by the following code. But it could not open D:\.
var directories = Directory.GetDirectories(ApplicationData.Current.LocalFolder.Path);
In UWP app you can only access two locations at default (local folder and install folder), others need capabilities setting or file open picker.Details please reference file access permission.
If you need access to all files in D:\, the user must manually pick the D:\ drive using the FolderPicker, then you have permissions to access to files in this drive.
var picker = new Windows.Storage.Pickers.FileOpenPicker();
picker.ViewMode = Windows.Storage.Pickers.PickerViewMode.Thumbnail;
picker.SuggestedStartLocation =
Windows.Storage.Pickers.PickerLocationId.ComputerFolder;
picker.FileTypeFilter.Add(".jpg");
picker.FileTypeFilter.Add(".jpeg");
picker.FileTypeFilter.Add(".png");
Windows.Storage.StorageFile file = await picker.PickSingleFileAsync();
if (file != null)
{
// Application now has read/write access to the picked file
}
else
{
//do some stuff
}

WP8.1 - C# - Overlapping audio with MediaComposition class

I am developing a voice recorder app for Windows Phone 8.1 that stores the recordings on the local storage and a cloud storage service.
Everything's almost done except the fact that being able to pause an ongoing recording is a strong requirement for this app and I have to get it done.
Now, since PauseRecordAsync() and ResumeRecordAsync() are not available for Windows Phone 8.1 in the MediaCapture class but they will be available in Windows 10, I had to make a workaround: Every time the pause button is pressed, an audio chunk is saved in the temp folder and that file is stored in an array. When the stop button is pressed, the last chunk is stored in the array and the following Concatenation function is called and a final audio temp file is created:
public async Task<IStorageFile> ConcatenateAudio([ReadOnlyArray]IStorageFile[] audioFiles, IStorageFolder outputFolder, string outputfileName)
{
IStorageFile _OutputFile = await outputFolder.CreateFileAsync(outputfileName, CreationCollisionOption.ReplaceExisting);
MediaComposition _MediaComposition = new MediaComposition();
MediaEncodingProfile _MediaEncodingProfile = MediaEncodingProfile.CreateM4a(AudioEncodingQuality.High);
foreach (IStorageFile _AudioFile in audioFiles)
{
if(_AudioFile != null)
{
BackgroundAudioTrack _BackgroundAudioTrack = await BackgroundAudioTrack.CreateFromFileAsync(_AudioFile);
MediaClip _MediaClip = MediaClip.CreateFromColor(Windows.UI.Colors.Black, _BackgroundAudioTrack.TrimmedDuration); // A dummy black video is created witn the size of the current audio chunk.
// Without this, the duration of the MediaComposition object is always 0.
// It's a messy workaround but it gets the job done.
// Windows 10 will dirrectly support PauseRecordAsync() and ResumeRecordAsync() for MediaCapture tho'. Yay! :D
_MediaClip.Volume = 0;
_BackgroundAudioTrack.Volume = 1;
_MediaComposition.Clips.Add(_MediaClip);
_MediaComposition.BackgroundAudioTracks.Add(_BackgroundAudioTrack);
}
}
TranscodeFailureReason _TranscodeFailureReason = await _MediaComposition.RenderToFileAsync(_OutputFile, MediaTrimmingPreference.Fast, _MediaEncodingProfile);
if (_TranscodeFailureReason != TranscodeFailureReason.None)
{
throw new Exception("Audio Concatenation Failed: " + _TranscodeFailureReason.ToString());
}
return _OutputFile;
}
The problem is that when I play the file, all the audio chunks are played from the beginning of the final audio file at the same time instead of playing the second one right after the first one ended and so on. They are all playing one over the other. The length of the file on the other hand is correct and after all audio files finished playing, it's total silence.
I figured it out. I had to manually set the delay for BackgroundAudioTrack.
Here is the working code:
public async Task<IStorageFile> ConcatenateAudio([ReadOnlyArray]IStorageFile[] audioFiles, IStorageFolder outputFolder, string outputfileName)
{
IStorageFile _OutputFile = await outputFolder.CreateFileAsync(outputfileName, CreationCollisionOption.ReplaceExisting);
MediaComposition _MediaComposition = new MediaComposition();
MediaEncodingProfile _MediaEncodingProfile = MediaEncodingProfile.CreateM4a(AudioEncodingQuality.High);
TimeSpan totalDelay = TimeSpan.Zero;
foreach (IStorageFile _AudioFile in audioFiles)
{
if (_AudioFile != null)
{
BackgroundAudioTrack _BackgroundAudioTrack = await BackgroundAudioTrack.CreateFromFileAsync(_AudioFile);
MediaClip _MediaClip = MediaClip.CreateFromColor(Windows.UI.Colors.Black, _BackgroundAudioTrack.TrimmedDuration); // A dummy black video is created witn the size of the current audio chunk.
// Without this, the duration of the MediaComposition object is always 0.
// It's a messy workaround but it gets the job done.
// Windows 10 will dirrectly support PauseRecordAsync() and ResumeRecordAsync() for MediaCapture tho'. Yay! :D
_MediaClip.Volume = 0;
_BackgroundAudioTrack.Volume = 1;
_MediaComposition.Clips.Add(_MediaClip);
_MediaComposition.BackgroundAudioTracks.Add(_BackgroundAudioTrack);
_BackgroundAudioTrack.Delay = totalDelay;
totalDelay += _BackgroundAudioTrack.TrimmedDuration;
}
}
TranscodeFailureReason _TranscodeFailureReason = await _MediaComposition.RenderToFileAsync(_OutputFile, MediaTrimmingPreference.Fast, _MediaEncodingProfile);
if (_TranscodeFailureReason != TranscodeFailureReason.None)
{
throw new Exception("Audio Concatenation Failed: " + _TranscodeFailureReason.ToString());
}
return _OutputFile;
}

Windows 8 GetFileAsync method gives UnAuthorized error

The below code an attempt to try and get get an Mp3 file from the MusicLibrary
It gives me,
A first chance exception of type
'System.UnauthorizedAccessException'
occurred in AccessingPictures.exe
This is my code:
public async void getFile()
{
StorageFolder folder = KnownFolders.MusicLibrary;
try
{
sampleFile = await folder.GetFileAsync("Test1.mp3");
}
catch (FileNotFoundException e)
{
// If file doesn't exist, indicate users to use scenario 1
Debug.WriteLine(e);
}
}
private void btnRead_Click(object sender, RoutedEventArgs e)
{
getFile();
}
Wouldn't we able to access the media files?
I am able to do this using the file picker.
But it does not work while i try to access it directly.
Am i missing anything here ?
To retrieve Pictures from Camera Roll
Void GetCameraPhotos()
{
using (var library = new MediaLibrary())
{
PictureAlbumCollection allAlbums = library.RootPictureAlbum.Albums;
PictureAlbum cameraRoll = allAlbums.Where(album => album.Name == "Camera Roll").FirstOrDefault();
var CameraRollPictures = cameraRoll.Pictures
}
}
You cannot access the files unless it is in response to a user request. i.e. the user must tap a button or something and that tap logic ends up calling your code that accesses the file. If you want to get at the file afterwards, you'll need to copy it in the app's data folder.
I finally figured the issue. It was because i hadn't enabled the capabilities in the Manifest file.
It works like a charm now.
Thanks everyone.

Categories

Resources