Xamarin iOS AVCaptureSession - iPhone 8 上只有 Audio/No 个视频
Xamarin iOS AVCaptureSession - Only Audio/No Video on iPhone 8
我们有一个使用 Xamarin Forms 构建的视频录制应用程序。对于 iOS 记录,我们有一个自定义渲染器,它执行如下操作:
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();
我们过去甚至只是将 .mov 文件重命名为 .mp4,它在所有浏览器上都能正常播放 - chrome 在 mac/pc 和 safari 上。我知道这不是个好主意,但它似乎奏效了。
这在 iPhone 8 之前一直工作得很好。现在,在 iPhone 8 上录制的任何视频在 Safari 中都可以正常工作,但在 chrome 上 mac 或 PC 上它只 播放音频而不播放视频 。
我知道苹果在最近的 iOS 版本中提供了一些新的 video/photo 格式,但这应该会影响 iPhone 7 Plus(运行 最新的iOS 和 "High Efficiency" 设置已在相机中启用。
将录制的视频直接编码为 mp4 视频有什么好的方法可以避免此类问题?
以上代码基于示例应用程序 - https://developer.xamarin.com/samples/monotouch/ios10/AVCam/
以下解决方案对我有用。
NSDictionary *outputSettings = [[NSDictionary alloc] initWithObjectsAndKeys:AVVideoCodecH264, AVVideoCodecKey, nil];
[movieFileOutput setOutputSettings:outputSettings forConnection:[movieFileOutput connectionWithMediaType:AVMediaTypeVideo]];
回答这个问题,因为几个人似乎面临着同样的问题。
我最终使用 AVExportSession 进行了转换。这似乎是进行转换的最佳方式,尽管我没有找到很多关于如何在 Xamarin 中正确执行此操作的示例。
查看下面我的代码片段:
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);
}
}
您可以直接指定输出使用的编解码器为H.264,避免需要以一种格式录制然后再转换为另一种格式:
var videoOutput = new AVCaptureMovieFileOutput();
var outputSettings = new NSDictionary(AVVideo.CodecKey, AVVideo.CodecH264);
videoOutput.SetOutputSettings(outputSettings, videoOutput.Connections[0]);
我们有一个使用 Xamarin Forms 构建的视频录制应用程序。对于 iOS 记录,我们有一个自定义渲染器,它执行如下操作:
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();
我们过去甚至只是将 .mov 文件重命名为 .mp4,它在所有浏览器上都能正常播放 - chrome 在 mac/pc 和 safari 上。我知道这不是个好主意,但它似乎奏效了。
这在 iPhone 8 之前一直工作得很好。现在,在 iPhone 8 上录制的任何视频在 Safari 中都可以正常工作,但在 chrome 上 mac 或 PC 上它只 播放音频而不播放视频 。
我知道苹果在最近的 iOS 版本中提供了一些新的 video/photo 格式,但这应该会影响 iPhone 7 Plus(运行 最新的iOS 和 "High Efficiency" 设置已在相机中启用。
将录制的视频直接编码为 mp4 视频有什么好的方法可以避免此类问题?
以上代码基于示例应用程序 - https://developer.xamarin.com/samples/monotouch/ios10/AVCam/
以下解决方案对我有用。
NSDictionary *outputSettings = [[NSDictionary alloc] initWithObjectsAndKeys:AVVideoCodecH264, AVVideoCodecKey, nil];
[movieFileOutput setOutputSettings:outputSettings forConnection:[movieFileOutput connectionWithMediaType:AVMediaTypeVideo]];
回答这个问题,因为几个人似乎面临着同样的问题。
我最终使用 AVExportSession 进行了转换。这似乎是进行转换的最佳方式,尽管我没有找到很多关于如何在 Xamarin 中正确执行此操作的示例。
查看下面我的代码片段:
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);
}
}
您可以直接指定输出使用的编解码器为H.264,避免需要以一种格式录制然后再转换为另一种格式:
var videoOutput = new AVCaptureMovieFileOutput();
var outputSettings = new NSDictionary(AVVideo.CodecKey, AVVideo.CodecH264);
videoOutput.SetOutputSettings(outputSettings, videoOutput.Connections[0]);