Home > OS >  FFmpeg video output is being zoomed in ONLY when video is taken in 30 FPS?
FFmpeg video output is being zoomed in ONLY when video is taken in 30 FPS?

Time:04-13

I have been using FFmpeg for about a month now, its been great.

I am capturing a video on IOS in either 60FPS or 30FPS. I am resizing the video to be 1:1 (or 4:3).

I am capturing my video with https://github.com/mrousavy/react-native-vision-camera

Everything is working fine with the default 60FPS. But, for some reason when the video is taken in 30FPS, the video gets zoomed in after the FFmpeg execution and I cannot figure out why...

Here is what my FFmpeg command looks like inside my function (React JS hook):

  const onMediaCaptured = useCallback(
    (media: PhotoFile | VideoFile, type: 'photo' | 'video') => {
      setIsProcessingMedia(!isProcessingMedia);

      var path =
        type === 'photo'
          ? RNFS.DocumentDirectoryPath   '/after.png'
          : RNFS.DocumentDirectoryPath   '/after.mp4';

      const portraitCrop =
        type === 'video' ? 'crop=1080:1350' : 'crop=1350:1080';

      const ffMPEGcmd = isSquareRatio
        ? `-y -i ${
            media.path
          } -aspect 1:1 -vf "crop=1080:1080:exact=1, scale=1080:1080, ${
            type === 'photo' ? 'transpose=1' : null
          }" -qscale 0 -b:v 10M ${path}`
        : `-y -i ${media.path} -vf "${portraitCrop}, ${
            type === 'photo' ? 'transpose=1' : null
          }" -b:v 10M -qscale 0 ${path}`;

      FFmpegKit.execute(ffMPEGcmd).then(async session => {
        const returnCode = await session.getReturnCode();
        if (ReturnCode.isSuccess(returnCode)) {
          // SUCCESS
          FFprobeKit.getMediaInformation(path)
            .then(async (session: MediaInformationSessionCamera) => {
              const information: MediaInformation =
                await session.getMediaInformation();
              const output = await session.getOutput();

              const outputJSON = JSON.parse(output);
              const newOne = outputJSON;

              const videoHeight = newOne.streams[0].height;
              const videoWidth = newOne.streams[0].width;

              setIsProcessingMedia(false);

              Actions.push('cameraMediaCaptured', {
                isSquareRatio: isSquareRatio,
                type: type,
                ratio: isSquareRatio ? 1080 / 1080 : 1350 / 1080,
                color: props.color,
                category: props.category,
                needsCrop: true,
                videoHeight: videoHeight,
                videoWidth: videoWidth,
                aspectRatio: videoHeight / videoWidth,
              });
            })
            .catch(error => console.error(error));
        } else if (ReturnCode.isCancel(returnCode)) {
          // CANCEL
        } else {
          // ERROR
          alert('error');
        }
      });
    },
    [isSquareRatio, props.category, props.color, isProcessingMedia],
  );

I appreciate any feedback I can get!

Cheers.

CodePudding user response:

Does it capture video at the same resolution at 30 & 60 fps? If not and 30 fps gives you a higher resolution video, crop filter would effectively give you a zoomed video. Use the input size expressions instead: something like crop=ih:ih Read the documentation. There are a lot of examples there as well. If you wish to use more complex expression so you don't need to do portrait/landscape detection in javascript, check out the FFmpeg expression syntax as well.

  • Related