I've been told that when I allow the user to create a video from within my app, a .jpg thumbnail image is supposed to be generated automatically. However, using windows phone power tools, I can see that only the video is generated, no image. Here is the code below:
EDIT: the QUESTION here, is HOW does one GET a thumbnail image from a given video that is saved in isolated storage?
' Set recording state: start recording.
Private Async Sub StartVideoRecording()
Try
App.ViewModel.IsDataLoaded = False
'isoStore = Await ApplicationData.Current.LocalFolder.GetFolderAsync("IsolatedStore")
strVideoName = GenerateVideoName()
isoFile = Await isoVideoFolder.CreateFileAsync(strVideoName, CreationCollisionOption.ReplaceExisting)
thisAccessStream = Await isoFile.OpenAsync(FileAccessMode.ReadWrite)
Await avDevice.StartRecordingToStreamAsync(thisAccessStream)
'save the name of the video file into the list of video files in isolated storage settings
Dim videoList As New List(Of InfoViewModel)
isoSettings = IsolatedStorageSettings.ApplicationSettings
If isoSettings.Contains("ListOfVideos") Then
videoList = isoSettings("ListOfVideos")
Else
isoSettings.Add("ListOfVideos", videoList)
End If
videoList.Add(New InfoViewModel With {.Name = strVideoName, .DateRecorded = Date.Now})
isoSettings("ListOfVideos") = videoList
isoSettings.Save()
isoSettings = Nothing
' Set the button states and the message.
UpdateUI(ButtonState.Recording, "Recording...")
Catch e As Exception
' If recording fails, display an error.
Me.Dispatcher.BeginInvoke(Sub() txtDebug.Text = "ERROR: " & e.Message.ToString())
End Try
End Sub
In Windows Phone 7.0 it wasn't possible using the "official" SDK to access the camera other than using CameraCaptureTask. But using Microsoft.Phone.InteropServices library it was possible to create a custom camera view in the application. If you used this VideoCamera class, it had an event called ThumbnailSavedToDisk, which might be what you have heard about. But apps using Microsoft.Phone.InteropServices was never allowed in the Windows Phone Marketplace. You can read more about it here.
To generate a thumbnail from a video file one solution would be to read up on how the MP4 file format works and extract one of the frames and use that as a thumbnail. Unfortunatly I haven't found any libraries that can do this.
Another, but far from optimal solution, would be to play the video in a MediaElement and then render that Control to a bitmap. This can be done with the following code (written in XAML/C#, I don't know VB.net, but should be easy to port):
<MediaElement
x:Name="VideoPlayer"
Width="640"
Height="480"
AutoPlay="True"
RenderTransformOrigin="0.5, 0.5"
VerticalAlignment="Center"
HorizontalAlignment="Center"
Stretch="Fill"
Canvas.Left="80"/>
And then to create the thumbnail:
// Set an event handler for when video has loaded
VideoPlayer.MediaOpened += VideoPlayer_MediaOpened;
// Read video from storage
IsolatedStorageFileStream videoFile = new IsolatedStorageFileStream("MyVideo.mp4", FileMode.Open, FileAccess.Read, IsolatedStorageFile.GetUserStoreForApplication());
VideoPlayer.SetSource(videoFile);
// Start playback
VideoPlayer.Play();
And then create the event handler which "captures" the thumbnail:
void VideoPlayer_MediaOpened(object sender, RoutedEventArgs e)
{
Thread.Sleep(100); // Wait for a short time to avoid black frame
WriteableBitmap wb = new WriteableBitmap(VideoPlayer, new TranslateTransform());
thumbnailImageHolder.Source = wb; // Setting it to a Image in the XAML code to see it
VideoPlayer.Stop();
}
Here is how it looks when using a modified version of the Video Recorder Sample. (The small image with the blue border in the upper right corner is the thumbnail of the recorded video. Behind is the camera Viewer.)
Related
Instead of creating a Windows built-in camera UI (CameraCaptureUI) or using a custom MediaCapture control and capture picture I want to open any Camera App downloaded in the device to capture an image and get the result.
I have used
string uriToLaunch = "microsoft.windows.camera:";
var uri = new Uri(uriToLaunch);
var success = await Windows.System.Launcher.LaunchUriAsync(uri);
But this just opens the camera app, I need to get the result file back to the app and save it.
Is there a way to do this?
The method you are using:
var success = await Windows.System.Launcher.LaunchUriAsync(uri);
just opens the default camera, nothing more, the result is a boolean with information if the application has been opened successfully, nothing more.
With CameraCaptureUI you don't need to create camera - this seems to be designed for the task like you have described. With lines:
var captureUI = new CameraCaptureUI();
captureUI.PhotoSettings.Format = CameraCaptureUIPhotoFormat.Jpeg;
captureUI.PhotoSettings.CroppedSizeInPixels = new Size(200, 200);
var photo = await captureUI.CaptureFileAsync(CameraCaptureUIMode.Photo);
you just launch the camera app and your app waits for the photo, which you can process further/save.
If you don't want to use it or implement own camera capture, you can think of sharing a picture taken by other app. This is described well at app-to-app communication at MSDN. In this case user will have to click Share button and choose your app as a target. That will invoke OnShareTargetActivated event where you can process the received content.
I am using MediaCapture to capture photos and store them. It works in the emulator. But when running the app on a real phone (Nokia Lumia 530) the captured photos are just black. They have a correct size and the file has a certain byte length, but when displaying the photo it's black. Please note that I do not use Silverlight and am fixed on using MediaCapture. The camera on the phone works when using the default camera app. The App's manifest includes the capabilities "Pictures Library" and "Webcam".
Does someone know what could be wrong?
Here is the test code I use:
using (var mediaCapture = new MediaCapture())
{
await mediaCapture.InitializeAsync();
ImageEncodingProperties imageFormat = ImageEncodingProperties.CreateJpeg();
StorageFile photoFile = await KnownFolders.PicturesLibrary.CreateFileAsync("TestPhoto.jpg", CreationCollisionOption.GenerateUniqueName);
await mediaCapture.CapturePhotoToStorageFileAsync(imageFormat, photoFile);
BitmapImage bitmap = new BitmapImage();
using (var photoStream = await photoFile.OpenReadAsync())
{
bitmap.SetSource(photoStream);
}
}
Edit
I found a solution. The photo is captured correctly if we have a CaptureElement, set it's source to the MediaCapture object, invoke MediaCapture.StartPreviewAsync before taking the photo, take the photo (using CapturePhotoToStorageFileAsync) and finally invoke StopPreviewAsync. It seems that MediaCapture needs an existing (and displayed) preview to be able to capture photos. Strange that this is not documented and using CapturePhotoToStorageFileAsync without a preview does not throw an Exception.
The photo is captured correctly if we have a CaptureElement, set it's source to the MediaCapture object, invoke MediaCapture.StartPreviewAsync before taking the photo, take the photo (using CapturePhotoToStorageFileAsync) and finally invoke StopPreviewAsync. It seems that MediaCapture needs an existing (and displayed) preview to be able to capture photos. Strange that this is not documented and using CapturePhotoToStorageFileAsync without a preview does not throw an Exception.
I am creating windows 8 store application with MonoGame framework. I want to get each bitmap from camera in order to process some image recognition on that bitmap. The thing is I only get the whole video stream from camera (randomAccessStream) but not each frame from the video.
async private void Start_Click(object sender, RoutedEventArgs e)
{
//1. Initialize:
mediaCaptureMgr = new MediaCapture();
randomAccessStream = new InMemoryRandomAccessStream();
await mediaCaptureMgr.InitializeAsync();
//2. create profile
MediaEncodingProfile encordingProfile = MediaEncodingProfile.CreateWmv(VideoEncodingQuality.Auto);
//3. start recording
await mediaCaptureMgr.StartRecordToStreamAsync(encordingProfile, randomAccessStream);
}
How can I receive new up-coming frame/bitmap from camera?
Take a look here
It is a sample app from Microsoft. Among other things it shows:
How to capture an image using the new LowLagPhotoCapture and LowLagPhotoControl classes.
How to capture a sequence of photos using the new LowLagPhotoSequenceCapture and LowLagPhotoSequenceControl classes.
...
If you are going to process the images, you could just take pictures on an interval. I don't think you need to process every single frame of a video stream..
I am recording a video in my app and uploading it to a server. The app is working fine for small videos but if the video is longer than 10 seconds the video size becomes very big and the app crashes.
How can I minimize the size of the video? Can I set the resolution? Can I also compress the video?
What else do you recommend I do to make sure the video is not gigantic?
Here is my code :
Public Sub InitializeVideoRecorder()
If captureSource Is Nothing Then
' Create the VideoRecorder objects.
captureSource = New CaptureSource()
fileSink = New FileSink()
videoCaptureDevice = CaptureDeviceConfiguration.GetDefaultVideoCaptureDevice()
' Add eventhandlers for captureSource.
AddHandler captureSource.CaptureFailed, AddressOf OnCaptureFailed
' Initialize the camera if it exists on the device.
If videoCaptureDevice IsNot Nothing Then
' Create the VideoBrush for the viewfinder.
videoRecorderBrush = New VideoBrush()
videoRecorderBrush.SetSource(captureSource)
' Display the viewfinder image on the rectangle.
viewfinderRectangle.Fill = videoRecorderBrush
' Start video capture and display it on the viewfinder.
captureSource.Start()
' Set the button state and the message.
UpdateUI(ButtonState.Initialized, "")
Else
' Disable buttons when the camera is not supported by the device.
UpdateUI(ButtonState.CameraNotSupported, "A camera is not supported on this device.")
End If
End If
End Sub
To reduce the video size we can make the resolution as much low.The code
VideoCaptureDevice webcam = CaptureDeviceConfiguration.GetDefaultVideoCaptureDevice();
int videoformatcount = webcam.SupportedFormats.Count(); //We will get the avilable video format
if (videoformatcount > 0)
{
var Temp = webcam.SupportedFormats;
VideoFormat objVideoFormat = Temp[videoformatcount - 1];
webcam.DesiredFormat = new VideoFormat(PixelFormatType.Format8bppGrayscale, objVideoFormat.PixelWidth, objVideoFormat.PixelHeight, 1);
}
captureSource.VideoCaptureDevice = webcam;
It will help you.The video must be in very low resolution(Available).
I am trying to change the Background of a button to an image source. I want to load that image in memory when we navigate to the page so that it doesn't flicker the first time it shows.
On Windows Phone, I was able to create the image source as such:
StreamResourceInfo resourceInfo = Application.GetResourceStream(uri);
BitmapImage bitmapSource = new BitmapImage();
// Avoid flicker by not delay-loading.
bitmapSource.CreateOptions = BitmapCreateOptions.None;
bitmapSource.SetSource(resourceInfo.Stream);
imageSource = bitmapSource;
I tried something similar in my Windows 8 Store app:
BitmapImage bitmapSource = new BitmapImage();
bitmapSource.CreateOptions = BitmapCreateOptions.None;
bitmapSource.UriSource = uri;
imageSource = bitmapSource;
but the same problem occurs. The button already has a different image as the Background, and on a certain event I would like it to change to the new background. But when I change the source, a noticeable flicker is observed. I'm assuming this is because the image is not yet in memory, as the issue goes away the second time the image source is modified.
Anyone know a solution? I need to somehow force the loading of this image.
Thanks!
If you use the SetSourceAsync method on the BitmapImage and await it before you attach it to the image source you should not see the flicker:-
// Ensure the stream is disposed once the image is loaded
using (IRandomAccessStream fileStream = await file.OpenAsync(Windows.Storage.FileAccessMode.Read))
{
// Set the image source to the selected bitmap
BitmapImage bitmapImage = new BitmapImage();
await bitmapImage.SetSourceAsync(fileStream);
imageSource = bitmapImage;
}
The MSDN docs have some more info on this
Thanks Ross, but what I ended up doing instead is I preloaded the half dozen or so bitmaps I needed by using similar code to what you had above, except from resource of course. I did this asynchronously when the page loaded, and then when I set the ImageSource on the button background, I used the already preloaded bitmaps. That way I know I'm not allocated a new chunk of memory for every instance of the bitmap.