arthenica / ffmpeg-kit

FFmpeg Kit for applications. Supports Android, Flutter, iOS, Linux, macOS, React Native and tvOS. Supersedes MobileFFmpeg, flutter_ffmpeg and react-native-ffmpeg.
https://arthenica.github.io/ffmpeg-kit
GNU Lesser General Public License v3.0
4.29k stars 579 forks source link

release mode not working on android, debug mode works fine(react-native) #481

Closed Liqiankun closed 2 years ago

Liqiankun commented 2 years ago

Description release mode not working on android, debug node works fine

Expected behavior works on both modes

Current behavior nothing happened

Screenshots Screenshot_20220703_175635

Logs No logs

Environment

Code

import React, { useState } from 'react';
import { SafeAreaView, Button, PermissionsAndroid, Alert } from 'react-native';
import { launchImageLibrary } from 'react-native-image-picker';
import CameraRoll from '@react-native-community/cameraroll';
import Spinner from 'react-native-loading-spinner-overlay';

import { FFmpegKit, ReturnCode } from 'ffmpeg-kit-react-native';

import RNFS from 'react-native-fs';

import { checkExternaltorage, isIOS } from '../../util/helpers';

const VideoCompressor = () => {
  const [loading, setLoading] = useState(false);
  const [progress, setProgress] = useState(0);
  const compressVideo = ({ uri, time }, callback) => {
    const finalVideo = `${RNFS.CachesDirectoryPath}/${Date.now()}.mp4`;

    cacheResourcePath(uri).then(rVideoUrl => {
      const str_cmd = `-i ${rVideoUrl} -c:v mpeg4 ${finalVideo}`; // `y -i ${rVideoUrl} -c:v libx264 -crf 28 -preset ultrafast  ${finalVideo}`;

      FFmpegKit.executeAsync(
        str_cmd,
        session => {
          const returnCode = session.getReturnCode();
          if (ReturnCode.isSuccess(returnCode)) {
            callback({
              videoPath: 'file://' + finalVideo
            });
          } else if (ReturnCode.isCancel(returnCode)) {
            setLoading(false);
            Alert.alert('提示', '压缩取消');
          } else {
            setLoading(false);
            Alert.alert('提示', '压缩失败');
          }
        },
        log => {
          Alert.alert('提示', log.getMessage());
        },
        statistics => {
          setProgress(Math.ceil((statistics.getTime() / 1000 / time) * 100));
        }
      );
    });
  };

  const cacheResourcePath = async sourcePath => {
    const uriComponents = sourcePath.split('/');
    const fileNameAndExtension = uriComponents[
      uriComponents.length - 1
    ].replaceAll(' ', '');

    const destPath = `${RNFS.CachesDirectoryPath}/${fileNameAndExtension}`;

    await RNFS.copyFile(sourcePath, destPath);
    return destPath;
  };

  const hasAndroidPermission = async () => {
    const permission = PermissionsAndroid.PERMISSIONS.WRITE_EXTERNAL_STORAGE;

    const hasPermission = await PermissionsAndroid.check(permission);
    if (hasPermission) {
      return true;
    }

    const status = await PermissionsAndroid.request(permission);
    return status === 'granted';
  };

  const savePicture = async videoPath => {
    if (!isIOS && !(await hasAndroidPermission())) {
      Alert.alert('提示', '无写入权限');
      setLoading(false);
      return;
    }

    console.log('---videoPath', videoPath);

    CameraRoll.save(videoPath, { type: 'video' })
      .then(res => {
        Alert.alert('提示', '压缩并保存成功');
        RNFS.unlink(videoPath);
        setLoading(false);
      })
      .catch(err => {
        Alert.alert('保存失败', JSON.stringify(err));
        setLoading(false);
      });
  };

  return (
    <SafeAreaView>
      <Button
        title="选择视频"
        onPress={() => {
          checkExternaltorage(isV => {
            if (isV) {
              launchImageLibrary(
                {
                  mediaType: 'video'
                },
                ({ assets }) => {
                  setLoading(true);
                  compressVideo(
                    { time: assets[0].duration, uri: assets[0].uri },
                    ({ videoPath }) => {
                      savePicture(videoPath);
                    }
                  );
                }
              );
            }
          });
        }}
      />
      <Spinner visible={loading} textContent={`压缩中...${progress}%`} />
    </SafeAreaView>
  );
};

export default VideoCompressor;
Liqiankun commented 2 years ago

I solved it. Then key is video path.

const finalVideo = `${RNFS.CachesDirectoryPath}/${Date.now()}.mp4`;
const str_cmd = `-i ${rVideoUrl} -c:v mpeg4 ${finalVideo}`; // `y -i ${rVideoUrl} -c:v libx264 -crf 28 -preset ultrafast  ${finalVideo}`;

      FFmpegKit.executeAsync(
        str_cmd,
        session => {
          const returnCode = session.getReturnCode();
          if (ReturnCode.isSuccess(returnCode)) {
            callback({
              videoPath: 'file://' + finalVideo
            });
          } else if (ReturnCode.isCancel(returnCode)) {
            setLoading(false);
            Alert.alert('提示', '压缩取消');
          } else {
            setLoading(false);
            Alert.alert('提示', '压缩失败');
          }
        },
        log => {
          Alert.alert('提示', log.getMessage());
        },
        statistics => {
          setProgress(Math.ceil((statistics.getTime() / 1000 / time) * 100));
        }
      );