Search code examples
c#iosxamarinavassetavassetexportsession

Xamarin C# Transcode .mov to .mp4 with AVAsset Native IOS


Problem: Our cross platform application (IOS & Android) cannot play videos on Android that originate from IOS.

Solution: Transcode .mov video files to .mp4 on client IOS applications prior to upload.

Issues: Unable to get the file location on IOS (string input is null). Not sure if my native code / approach is sound.

Exception: Error Domain=AVFoundationErrorDomain Code=-11800 "The operation could not be completed"

Shared Code:

try
        {
            MediaPickResult pickresult = await MediaGallery.PickAsync(1, MediaFileType.Video);

            if (pickresult != null)
            {
                foreach (var video in pickresult.Files)
                {
                    string guid = Guid.NewGuid().ToString();
                    blobupload.BlobID = guid + ".mp4";
                    string inputfilename = video.NameWithoutExtension + "." + video.Extension;
                    string input = Path.Combine(Environment.GetFolderPath(Environment.SpecialFolder.Personal), inputfilename);
                    string output = Path.Combine(AzureStorage.localpath, guid + ".mp4");

                    if (File.Exists(input))
                    {
                        await IVideoConverter.ConvertVideo(input, output);
                    }
                }
            }

Native IOS:

public async Task ConvertVideo(string inputpath, string outputpath)
    {
        //string OutputFilePath = Path.ChangeExtension(outputpath, "mp4");
        AVAsset asset = AVAsset.FromUrl(NSUrl.FromFilename(inputpath));
        AVAssetExportSession export = new AVAssetExportSession(asset, AVAssetExportSession.PresetPassthrough);

        
        export.OutputUrl = NSUrl.FromFilename(outputpath);
        export.OutputFileType = AVFileType.Mpeg4;
        export.ShouldOptimizeForNetworkUse = true;

        var results = export.DetermineCompatibleFileTypesAsync();
        try
        {
            export.ExportAsynchronously(() =>
            {
                if (export.Error != null)
                {
                    System.Diagnostics.Debug.WriteLine(export.Error.LocalizedDescription);
                }
            });
        }
        catch (Exception ex)
        {

            System.Diagnostics.Debug.WriteLine(ex);
        }

Solution

  • I'd suggest

    1. get the stream from the MediaFile
    2. write to a local app folder
    3. pass the path to that local copy to ConvertVideo