hugger
hugger

Reputation: 488

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

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.

Upvotes: 0

Views: 623

Answers (1)

kesh
kesh

Reputation: 5463

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.

Upvotes: 1

Related Questions