Windows Phone 8.1 MediaComposition - Audio Too Fast When Stitching Videos - c#

I am having a problem when trying to concatenate multiple videos together. Whenever I combine 2 or more videos, the audio is played at double speed, while the video plays out normally.
Below is the code. Am I missing something?
I get the same results when testing but cloning a single video or selecting multiple videos.
I have compared to the code example here (I am not trimming).
public static IAsyncOperation<IStorageFile> ConcatenateVideoRT([ReadOnlyArray]IStorageFile[] videoFiles, IStorageFolder outputFolder, string outputfileName)
{
return Task.Run<IStorageFile>(async () =>
{
IStorageFile _OutputFile = await outputFolder.CreateFileAsync(outputfileName, CreationCollisionOption.GenerateUniqueName);
MediaComposition _MediaComposition = new MediaComposition();
foreach (IStorageFile _VideoFile in videoFiles)
{
MediaClip _MediaClip = await MediaClip.CreateFromFileAsync(_VideoFile);
_MediaComposition.Clips.Add(_MediaClip);
_MediaComposition.Clips.Add(_MediaClip.Clone());
}
TranscodeFailureReason _TranscodeFailureReason = await _MediaComposition.RenderToFileAsync(_OutputFile);
if (_TranscodeFailureReason != TranscodeFailureReason.None)
{
throw new Exception("Video Concatenation Failed: " + _TranscodeFailureReason.ToString());
}
return _OutputFile;
}).AsAsyncOperation();
}

It looks like there are two issues. I have got this working by adding the following line:
MediaEncodingProfile _MediaEncodingProfile = MediaEncodingProfile.CreateMp4(VideoEncodingQuality.Vga);
And changing the following line:
TranscodeFailureReason _TranscodeFailureReason = await _MediaComposition.RenderToFileAsync(_OutputFile);
To:
TranscodeFailureReason _TranscodeFailureReason = await _MediaComposition.RenderToFileAsync(_OutputFile, MediaTrimmingPreference.Fast, _MediaEncodingProfile);
The problem seems to be that RenderToFileAsync doesn't appear to work properly when using VideoEncodingQuality.HD720p or VideoEncodingQuality.HD1080p, both of these settings recreate the fast audio issue. Also, using VideoEncodingQuality.Auto seems to cause the encode to fail (although I think it is meant to use the default settings from the camera).
Additionally, I posted the problem on the Microsoft Partner Community Forums and their response was that encoding can fail on specific devices, e.g. in their tests video recorded on a Lumia 638 could not be encoded/concatenated even on other devices, but video from a HTC 8x, Lumia 920 and Lumia 930 could be encoded on all devices even the 638.
They suggested this was a device problem (firmware) not a Windows.Media.Editing API problem.

Related

Decoding Barcode using Zxing library works on 1 tablet but does not work on another tablet

I have written a windows store app in XAML & C# to read image from tablet's webcam and decode the barcode using Zxing's lbrary. The code is working fine on a given tablet having an i5 processor while it fails to run on an actual tablet with 2MP camera and "Intel Baytrail Quad-Core" processor.
Any ideas on why this could happen?
Please let me know if you need to see my code for this issue ad I will share.
I am wondering how can the same code work on 1 tablet while fail on another tablet.
Thanks in advance for any help provided.
EDIT
Code used to scan the barcode and read as below - The last if/else block is what I get to. No exception raised :(
string barcodeData = string.Empty;
using (var imageStream = new InMemoryRandomAccessStream())
{
processingImage = true;
var encodingProperties = new ImageEncodingProperties();
encodingProperties.Subtype = "Jpeg";
encodingProperties.Width = 400;
encodingProperties.Height = 400;
await captureMgr.CapturePhotoToStreamAsync(encodingProperties, imageStream);
await imageStream.FlushAsync();
imageStream.Seek(0);
var bitmap = new WriteableBitmap(400, 400);
bitmap.SetSource(imageStream);
preview1.Source = bitmap; //preview1 is an Image control to display the captured image
BitmapImage bitmapImage = new BitmapImage();
bitmapImage.SetSource(imageStream);
imageStream.Seek(0);
var bitmapDecoder = await BitmapDecoder.CreateAsync(BitmapDecoder.JpegDecoderId, imageStream);
var data = await bitmapDecoder.GetPixelDataAsync(
BitmapPixelFormat.Bgra8,
BitmapAlphaMode.Straight,
new BitmapTransform(),
ExifOrientationMode.IgnoreExifOrientation,
ColorManagementMode.DoNotColorManage
);
if (data != null)
{
BarcodeReader barcodeReader = new BarcodeReader();
var result = barcodeReader.Decode(
data.DetachPixelData(),
(int)bitmapDecoder.PixelWidth,
(int)bitmapDecoder.PixelHeight,
ZXing.RGBLuminanceSource.BitmapFormat.BGR32
);
if (result != null)
{
//Barcode found
}
else
//No data found.
}
}
I guess you are using ZXing.NET library.
Have you ever considered moving to another barcode scanner library?
Accessing the "ISSUES" section in ZXing.NET Library, you can see that there's a lot of bugs still opened for Windows Phone (and should be Window Store also).
http://zxingnet.codeplex.com/workitem/list/basic
One of it called my attention. Check out this comment:
While the WP samples all target Silverlight, you must not forget that the new WP8.1 base is WinRT - so I suggest you use the WinRT sample as a base.
I tried to do the same, but truth to be told, ZXing lacks a lot ATM for WinRT Universal Apps - it's slow, unreliable, and barely ever recognizes a thing.
http://zxingnet.codeplex.com/workitem/13311
I don't know how reliable this is, but the last time the project was updated was on April 7th!!!!
You should really consider changing you library!
Hi,
I made a lib for WinRT using ZXing & Imaging SDK.
It works well (but does not include any additional focus feature).
https://github.com/stepheUp/VideoScanZXing4WP81
There is a lib and a sample app that you can try.
It works for barcodes and QRCode (barcode by default but just change the optional parameter in the scan function code to use QRCode)
Hope it helps,
Stéphanie

LiveSDK for Universal Windows App background upload

I'm developing Universal Windows App and use Live SDK 5.6 to upload files to OneDrive. I see examples of usage here and instructions about versions here.
According to instructions I should use:
For Windows and WP81: CreateBackgroundUploadAsync method;
For WP8 Silverlight: BackgroundUploadAsync method
CreateBackgroundUploadAsync works like a charm on Windows and returns correct progress values by LiveOperationProgress but on a WP81 it shows 0% progress all the time and at last it becames 100%. So it actually does not track progress.
Then I tried to use BackgroundUploadAsync(it is for Silverlight apps) and it works on phone - uploads file and tracks progress right. But when I tried to upload big file(in my case > 150Mb) I noted that exactly after 120 seconds upload operation just resets to 0% and starts again without any exceptions.
Here is code for Windows & WP81 approach:
var progressHandler = new Progress<LiveOperationProgress>(
(progress) =>
{
var res = progress.ProgressPercentage;
});
LiveUploadOperation uploadOperation = await liveConnectClient.CreateBackgroundUploadAsync(uploadPath, "testfile.wav", file, OverwriteOption.Rename);
LiveOperationResult uploadResult = await uploadOperation.StartAsync(new CancellationToken(), progressHandler);
And for Silverlight:
var progressHandler = new Progress<LiveOperationProgress>(
(progress) =>
{
var res = progress.ProgressPercentage;
});
LiveOperationResult opResult = await connectClient.BackgroundUploadAsync(CurrentFolderId,
file.Name,
stream,
OverwriteOption.Rename,
record.GetCTS().Token,
progressHandler);
So question - how to make it upload files of any size, redefine timeout(currently 120s) and track progress on both Windows and WP81?
UPD:
I found the reason of 2 mins timeout here:
After the connection has been established, an HTTP request message that has not received a response within two minutes is aborted.
Is it normal for PUT request?

Captured photo with stripes

I'm using MediaCapture class to take a photo with Windows Phone 8.1 Runtime. The code, where I take a picture looks like this:
// create a file
StorageFile photoFile = await ApplicationData.Current.LocalFolder.CreateFileAsync("myFirstPhoto.jpg", CreationCollisionOption.ReplaceExisting);
// take a photo with choosen Encoding
await captureManager.CapturePhotoToStorageFileAsync(ImageEncodingProperties.CreateJpeg(), photoFile);
The code is working quite fine, as I get a picture, but with strange stripes on left and right side:
I'm trying to find a solution for this problem, but without success. Am I missing something?
EDIT - Photos takes from build-in app are without stripes, so this seems not to be a problem with hardware.
Ok I've figured it out myself - it's a problem with resolution which is set as default when using MediaCapture. If you set maximum resolution just after Initializing MediaCapture then there will be no stripes:
// just after initialization
var maxResolution = captureManager.VideoDeviceController.GetAvailableMediaStreamProperties(MediaStreamType.Photo).Aggregate(
(i1, i2) => (i1 as VideoEncodingProperties).Width > (i2 as VideoEncodingProperties).Width ? i1 : i2);
await captureManager.VideoDeviceController.SetMediaStreamPropertiesAsync(MediaStreamType.Photo, maxResolution);
I tried with the lowest resolution it gets the same stripes.
From MS Advance Camera sample, they use MediaCapture for preview but SilverLight API for capturing!
The MediaCapture has also memory leak issue each time when you call CapturePhotoToXXX API.
I wonder if they already know MediaCapture is badly managed on WindowsPhone 8.1 and this is the reason why they don't provide a Camera MediaCapture sample with RT APIs.

Photo capture on Windows Store App for Windows Phone

Well, my question is simple:
How do I capture pictures with a Windows Store App for Windows Phone 8.1, using the camera?
The samples on MSDN use Windows.Media.Capture.CameraCaptureUI, which is not usable on Windows Phone, or are for Silverlight.
I can't find any doc or sample specifically for Windows Phone app using Windows Runtime.
If someone knows, or even have the doc for this, I would be glad.
In WP8.1 Runtime (also in Silverlight) you can use MediaCapture. In short:
// First you will need to initialize MediaCapture
Windows.Media.Capture.MediaCapture takePhotoManager = new Windows.Media.Capture.MediaCapture();
await takePhotoManager.InitializeAsync();
If you need a preview you can use a CaptureElement:
// In XAML:
<CaptureElement x:Name="PhotoPreview"/>
Then in the code behind you can start/stop previewing like this:
// start previewing
PhotoPreview.Source = takePhotoManager;
await takePhotoManager.StartPreviewAsync();
// to stop it
await takePhotoManager.StopPreviewAsync();
Finally to take a Photo you can for example take it directly to a file CapturePhotoToStorageFileAsync or to a Stream CapturePhotoToStreamAsync:
ImageEncodingProperties imgFormat = ImageEncodingProperties.CreateJpeg();
// a file to save a photo
StorageFile file = await ApplicationData.Current.LocalFolder.CreateFileAsync(
"Photo.jpg", CreationCollisionOption.ReplaceExisting);
await takePhotoManager.CapturePhotoToStorageFileAsync(imgFormat, file);
If you want to capture video then here is more information.
Also don't forget to add Webcam in Capabilities of your manifest file, and Front/Rear Camera in Requirements.
In case you need to choose a Camera (fornt/back), you will need to get the Camera Id and then initialize MediaCapture with desired settings:
private static async Task<DeviceInformation> GetCameraID(Windows.Devices.Enumeration.Panel desired)
{
DeviceInformation deviceID = (await DeviceInformation.FindAllAsync(DeviceClass.VideoCapture))
.FirstOrDefault(x => x.EnclosureLocation != null && x.EnclosureLocation.Panel == desired);
if (deviceID != null) return deviceID;
else throw new Exception(string.Format("Camera of type {0} doesn't exist.", desired));
}
async private void InitCamera_Click(object sender, RoutedEventArgs e)
{
var cameraID = await GetCameraID(Windows.Devices.Enumeration.Panel.Back);
captureManager = new MediaCapture();
await captureManager.InitializeAsync(new MediaCaptureInitializationSettings
{
StreamingCaptureMode = StreamingCaptureMode.Video,
PhotoCaptureSource = PhotoCaptureSource.Photo,
AudioDeviceId = string.Empty,
VideoDeviceId = cameraID.Id
});
}
In universal Windows Phone 8.1 (WinRT) apps it is no longer possible to jump directly into the built-in camera app and receive a callback when a picture was taken.
To do that you have to implement Windows.Media.Capture.MediaCapture as described above. There used to be CameraCatureUI but it is not available in WinRT apps for Windows Phone 8.1.
However there is a "workaround". You can use Windows.Storage.Pickers.FileOpenPicker and configure it to pick images. Now the picker will have a camera-button. The user can click the camera-button and the built-in camera app will open. Once the user has taken a picture you will receive a callback in your app. The FileOpenPicker callback is a little annoying to implement, but it works. If you can live with the usability implications this might be a valid approach.
There was a session on this topic during Microsofts build-Conference in 2014. You can watch the session online with this link.
You can take the approach on this link. Everything is explained very nicely.
Just use the PhotoCamera class and don't forget to enable camera usage in your app manifest

Recording (or transforming after recording) video at non-standard size in Windows Phone 8

I am trying to capture MP4 video at a specific resolution in Windows Phone 8 (to be specific, 480x480). I know that I can't use sizes other than the presets, and 480x480 is not a preset. How do I transform a captured video (such as 640x480) and crop the top and bottom to make it 480x480? Any free or open source libraries (that run on Windows Phone) are welcome. Please don't answer with answers such as 'use an external server', I need an on-device solution.
Use the Windows.Phone.Media.Capture APIs and the AudioVideoCaptureDevice class
Second parameter for AudioVideoCaptureDevice.OpenAsync - see this link - is the resolution. And you can get the resolutions using AudioVideoCaptureDevice.GetAvailableCaptureResolutions(sensor)
EDIT: To set custom resolutions try AudioVideoCaptureDevice.SetCaptureResolutionAsync
EDIT 2: You could try something like the following to transform recorded video: (can't find where i got the code from soz to author!)
StorageFolder isoStore = await ApplicationData.Current.LocalFolder.GetFolderAsync("Shared");
var file = await isoStore.CreateFileAsync("foos1.wmv", CreationCollisionOption.ReplaceExisting);
using (var s = await file.OpenAsync(FileAccessMode.ReadWrite))
{
Windows.Foundation.Size resolution = new Windows.Foundation.Size(640, 480);
avDevice = await AudioVideoCaptureDevice.OpenAsync(CameraSensorLocation.Back,
AudioVideoCaptureDevice.GetAvailableCaptureResolutions(CameraSensorLocation.Back).Last());
VideoBrush videoRecorderBrush = new VideoBrush();
videoRecorderBrush.SetSource(avDevice);
viewfinderRectangle.Fill = videoRecorderBrush;
await avDevice.StartRecordingToStreamAsync(s);
Thread.Sleep(30000);
await avDevice.StopRecordingAsync();
}
new MediaPlayerLauncher()
{
Media = new Uri(file.Path, UriKind.Relative),
}.Show();

Categories

Resources