Reputation: 2416
We have a video recording app built with Xamarin Forms. For the iOS recording we have a custom renderer which does something like this:
NSError error;
var CaptureSession = new AVCaptureSession();
CaptureSession.SessionPreset = AVCaptureSession.PresetMedium;
var videoDevices = AVCaptureDevice.DevicesWithMediaType(AVMediaType.Video);
var cameraPosition = AVCaptureDevicePosition.Front;
var device = videoDevices.FirstOrDefault(d => d.Position == cameraPosition);
var input = new AVCaptureDeviceInput(device, out error);
CaptureSession.AddInput(input);
var audioDevice = AVCaptureDevice.GetDefaultDevice(AVMediaType.Audio);
var audioDeviceInput = AVCaptureDeviceInput.FromDevice(audioDevice, out error);
CaptureSession.AddInput(audioDeviceInput);
CaptureSession.StartRunning();
// ...
// ...
var MovieFileOutput = new AVCaptureMovieFileOutput();
CaptureSession.AddOutput(MovieFileOutput);
var basePath = Environment.GetFolderPath(Environment.SpecialFolder.ApplicationData);
var outputFilePath = Path.Combine(basePath, Path.ChangeExtension("video", "mov"));
MovieFileOutput.StartRecordingToOutputFile(NSUrl.FromFilename(outputFilePath), this);
// ...
// ...
MovieFileOutput.StopRecording();
We used to even just rename the .mov file to .mp4 and it played fine on all browsers - chrome on mac/pc & safari. I know this is not a good idea but it just seemed to work.
This used to work absolutely fine until iPhone 8. Now any video recorded on iPhone 8 works fine in Safari, but on chrome for mac or pc it just plays the audio but no video.
I know that apple has come with some new video/photo formats in the recent iOS release, but that should have affected iPhone 7 Plus(running the latest iOS and "High Efficiency" setting enabled in the camera).
What is a good way to encode the recorded video as a mp4 video directly so such issues dont occur?
The above code was based on the sample app - https://developer.xamarin.com/samples/monotouch/ios10/AVCam/
Upvotes: 1
Views: 1019
Reputation: 1118
You can directly specify the codec used for the output to be H.264, avoiding the need to record in one format and then convert to another:
var videoOutput = new AVCaptureMovieFileOutput();
var outputSettings = new NSDictionary(AVVideo.CodecKey, AVVideo.CodecH264);
videoOutput.SetOutputSettings(outputSettings, videoOutput.Connections[0]);
Upvotes: 0
Reputation: 2416
Answering this question as a couple of people seem to be facing the same issue.
I ended up using AVExportSession to do the conversion. This seems like the best way to do the conversion though I did not find many examples on how to do this right in Xamarin.
See below a snippet of my code:
private void ExportToMP4()
{
var basePath = Environment.GetFolderPath(Environment.SpecialFolder.ApplicationData);
var inputFilePath = Path.Combine(basePath, "test.mov");
var outputFilePath = Path.Combine(basePath, "test.mp4");
var asset = AVAsset.FromUrl(NSUrl.FromFilename(inputFilePath));
AVAssetExportSession export = new AVAssetExportSession(asset, AVAssetExportSession.PresetMediumQuality);
export.OutputUrl = NSUrl.FromFilename(outputFilePath);
export.OutputFileType = AVFileType.Mpeg4;
export.ShouldOptimizeForNetworkUse = true;
try
{
//Reference : https://forums.xamarin.com/discussion/62537/xamarin-ios-mov-to-mp4-conversion
export.ExportAsynchronously(() =>
{
if (export.Error != null)
{
System.Diagnostics.Debug.WriteLine(export.Error.LocalizedDescription);
}
else
{
InvokeOnMainThread(() =>
{
// Success! Do what needs to be done...
});
}
});
}
catch (Exception ex)
{
System.Diagnostics.Debug.WriteLine(ex);
}
}
Upvotes: 0
Reputation: 4713
Following solution worked for me.
NSDictionary *outputSettings = [[NSDictionary alloc] initWithObjectsAndKeys:AVVideoCodecH264, AVVideoCodecKey, nil];
[movieFileOutput setOutputSettings:outputSettings forConnection:[movieFileOutput connectionWithMediaType:AVMediaTypeVideo]];
Upvotes: 1