apache / cordova-plugin-media-capture

Apache Cordova Media Capture Plugin
https://cordova.apache.org/
Apache License 2.0
307 stars 495 forks source link

MediaFile.getFormatData() incorrect width/height after video capture on iOS #236

Open alexwilson-motasoft opened 2 years ago

alexwilson-motasoft commented 2 years ago

Bug Report

Problem

MediaFile.getFormatData() displays the same width/height regardless of video capture orientation on iOS.

What is expected to happen?

Expected to get the videos dimensions so I can figure out the orientation the video was captured in.

What does actually happen?

Calling MediaFile.getFormatData() always gives this object:

{
    "width": 480,
    "height": 360,
    "duration": x.x // this is correct,
    "codecs": null,
    "bitrate": 0
}

Information

Using this to get the media orientation

    private getOrientation(mediaFormatData: MediaFileData): string {
        if (mediaFormatData.height > mediaFormatData.width) {
            return "PORTRAIT";
        }

        if (mediaFormatData.height < mediaFormatData.width) {
            return "LANDSCAPE";
        }

        return "SQUARE";
    }

Command or Code

CaptureVideo(): Promise<File> {

        return new Promise<File>((resolve, reject) => {
            const options: CaptureVideoOptions = {
                limit: 1,
                duration: 120, // Seconds
            };

            this.mediaCapture.captureVideo(options).then(
                async (mediaData: MediaFile[]) => {

                    console.log(`File size: ${mediaData[0].size / 1000000} MB`);

                    mediaData[0].getFormatData(
                    (mediaFormatData: MediaFileData) => {
                        console.log(mediaFormatData);
                        const orientation = this.getOrientation(mediaFormatData);
                        console.log(orientation);

                        if (this.platform.is("ios")) {
                            const file = 'file://' + mediaData[0].fullPath;

                            this.file
                            .resolveLocalFilesystemUrl(file)
                            .then((entry: FileEntry) => {
                                entry.file((entryContext) => {
                                    // webkitRelativePath is a read-only non standard property
                                    // https://developer.mozilla.org/en-US/docs/Web/API/File/webkitRelativePath
                                    // @ts-ignore
                                    resolve(entryContext);                          
                                });
                            })
                            .catch((entryErr: Error) => {
                                console.log(mediaData[0].fullPath);
                                console.log("[IOS] Error while reading file.", entryErr.message);
                                reject();
                            });
                        } else if (this.platform.is("android")) {
                            this.file
                                .resolveLocalFilesystemUrl(mediaData[0].fullPath)
                                .then((entry: FileEntry) => {
                                    entry.file((entryCntx) => {                                         
                                        // webkitRelativePath is a read-only non standard property
                                        // https://developer.mozilla.org/en-US/docs/Web/API/File/webkitRelativePath
                                        // @ts-ignore
                                        resolve(entryCntx);                                                 
                                    });
                                })
                                .catch((readVideoErr) => {
                                    console.log("Error while reading file.", readVideoErr);
                                    reject();
                                });
                        }

                    }, (err) => {
                        console.log("Error getting media format.", err);
                        reject();
                    });
                },
                (captureVideoErr) => {
                    if (captureVideoErr.message !== 'Canceled.') {
                        // Handle error
                        console.log("Error while taking video.", captureVideoErr);
                    }
                    reject();
                }
            );
        });
    }

Environment, Platform, Device

Ionic, Cordova IOS 6.0.2, iPhone XR, iOS 14.4.1

Version information

Ionic:
   Ionic CLI                     : 5.4.16
   Ionic Framework               : @ionic/angular 5.6.5
   @angular-devkit/build-angular : 0.901.4
   @angular-devkit/schematics    : 9.1.4
   @angular/cli                  : 9.1.4
   @ionic/angular-toolkit        : 2.3.3

Cordova:
   Cordova CLI       : 10.0.0 (cordova-lib@10.1.0)
   Cordova Platforms : ios 6.2.0
   Cordova Plugins   : cordova-plugin-ionic 5.4.7, cordova-plugin-ionic-keyboard 2.2.0, cordova-plugin-ionic-webview 5.0.0, (and 35 other plugins)

Utility:
   cordova-res                          : not installed
   native-run (update available: 1.5.0) : 0.3.0

System:
   ios-deploy : 1.9.4
   ios-sim    : 8.0.2
   NodeJS     : v10.13.0 (/usr/local/bin/node)
   npm        : 6.14.13
   OS         : macOS Big Sur

Checklist

alexwilson-motasoft commented 2 years ago

Work around using another plugin for others coming across this issue. In combination with this plug in, use cordova-plugin-video-editor and use their GetVideoInfo() function to provide accurate orientation with out extra logic, regardless of platform.

Here is an example using Ionic's types in an angular app.

private async getOrientation(fileUrl: string): Promise<string> {
    const videoInfo = await this.videoEditor.getVideoInfo({
        fileUri: fileUrl
    });

    return videoInfo.orientation;
}