【问题标题】:In Android, how to render a video with Filters by VidEffects在 Android 中,如何使用 VidEffects 的过滤器渲染视频
【发布时间】:2018-07-04 08:34:44
【问题描述】:

我可以使用 VidEffects (https://github.com/krazykira/VidEffects) 成功地将过滤器应用于我的应用中录制的视频。问题是这样的插件不会渲染过滤的视频,无论如何我试图通过使用这个类来应用永久的视频效果:

public class VideoProcessing extends AsyncTask {
    private final File myDirectory;
    private FFmpegFrameGrabber VIDEO_GRABBER;
    private FFmpegFrameRecorder videoRecorder;
    File file;
    int totalLength;
    private Context mContext;
    private FFmpegFrameFilter filter;

    VideoProcessing(Context context, String path) {
        mContext = context;
        file = new File(path);
        VIDEO_GRABBER = new FFmpegFrameGrabber(file);
        myDirectory = new File(Environment.getExternalStoragePublicDirectory(Environment.DIRECTORY_PICTURES) + "/_Pikky-Edited-Video/");
        Log.i(Configurations.TAG, "VIDEO PROCESSING PATH: " + myDirectory);

        if (!myDirectory.exists()) { myDirectory.mkdirs(); }
    }


    @Override
    protected void onPreExecute() {
        super.onPreExecute();
    }

    @Override
    protected Object doInBackground(Object[] params) {
        Log.i(Configurations.TAG, "DO IN BACKGROUND: " + params);
        Frame tempVideoFrame;
        try {
            VIDEO_GRABBER.start();
            initVideoRecorder(myDirectory + "/video" + System.currentTimeMillis() + ".mp4");
            filter.start();
            while (VIDEO_GRABBER.grab() != null) {
                tempVideoFrame = VIDEO_GRABBER.grabImage();
                if (tempVideoFrame != null) {
                    filter.push(tempVideoFrame);
                    tempVideoFrame = filter.pull();
                    videoRecorder.record(tempVideoFrame);
                }
            }
            filter.stop();
            videoRecorder.stop();
            videoRecorder.release();
            VIDEO_GRABBER.stop();
            VIDEO_GRABBER.release();

            Log.i(Configurations.TAG, "VIDEO GRABBER STOP");

        } catch (FrameGrabber.Exception | FrameRecorder.Exception | FrameFilter.Exception e) { e.printStackTrace(); }
        return null;
    }


    @Override
    protected void onPostExecute(Object o) {
        super.onPostExecute(o);
        Log.i(Configurations.TAG, "ON POST EXECUTED: " + o);
    }


    private void initVideoRecorder(String path) {
        try {
            // FFmpeg effect/filter that will be applied
            filter = new FFmpegFrameFilter("colorchannelmixer=.393:.769:.189:0:.349:.686:.168:0:.272:.534:.131", VIDEO_GRABBER.getImageWidth(), VIDEO_GRABBER.getImageHeight());
            videoRecorder = FFmpegFrameRecorder.createDefault(path, VIDEO_GRABBER.getImageWidth(), VIDEO_GRABBER.getImageHeight());
            videoRecorder.start();
            Log.i(Configurations.TAG, "VIDEO PROCESSING - VIDEO RECORDER START");

        } catch (FrameRecorder.Exception e) { e.printStackTrace(); }
    }
}

这个类在我的 EditVideo 活动的 switch 案例中被调用,如下所示 - 其中 surfaceView 是一个自定义 GLSurfaceView

 case 2: surfaceView.init(mediaPlayer, new InvertColorsEffect());
                            new VideoProcessing(EditVideo.this, Configurations.videoToShareURL);
                        break;

无论如何,doInBackground 函数似乎没有在任何地方被调用,因为该应用只在我的 Pictures 目录中创建自定义文件夹(_Pikky-Edited-Video em>),在 Logcat 中打印其路径 - 见 Log.i(Configurations.TAG, "VIDEO PROCESSING PATH: " + myDirectory); 仅此而已,视频预览会在我的 Activity 中继续播放 - 这是因为我已将 MediaPlayer 的循环设置为 true - 但我的 VideoProcessing 类的其他功能不要被叫,initVideoRecorder()

这是我的 build.gradle,所有必要的依赖项都已下载:

    implementation 'com.writingminds:FFmpegAndroid:0.3.2'
    implementation group: 'org.bytedeco', name: 'javacv', version: '1.1'
    implementation group: 'org.bytedeco.javacpp-presets', name: 'opencv', version: '3.0.0-1.1', classifier: 'android-arm'
    implementation group: 'org.bytedeco.javacpp-presets', name: 'ffmpeg', version: '2.8.1-1.1', classifier: 'android-arm'

我也对使用过滤器渲染视频的替代解决方案持开放态度。

【问题讨论】:

    标签: java android video effects


    【解决方案1】:

    解决方案:

    我发现这个很棒且易于实现的框架:https://github.com/MasayukiSuda/Mp4Composer-android

    只需在 build.gradle 中添加其依赖即可:

    dependencies {
            // jCenter
            implementation 'com.daasuu:Mp4Composer-android:0.1.6'
        }
    

    并使用此代码根据每种效果导出过滤后的视频:

    renderVideoIntoMp4(myVideoURL, new GlInvertFilter()); // add the Filter you want
    
    
    void renderVideoIntoMp4(String filePath, GlFilter filter) {
        tempVideoPath = getVideoFilePath();
                //Environment.getExternalStoragePublicDirectory(Environment.DIRECTORY_PICTURES).getAbsolutePath() + "/temp_video.mp4";
    
        new Mp4Composer(filePath, tempVideoPath)
                // .rotation(Rotation.ROTATION_270)
                //.size(720, 1280)
                .fillMode(FillMode.PRESERVE_ASPECT_FIT)
                .filter(filter)
                .mute(false)
                .flipHorizontal(false)
                .flipVertical(false)
                .listener(new Mp4Composer.Listener() {
                    @Override
                    public void onProgress(double progress) {
                        Log.i(Configurations.TAG, "SAVING PROGRESS: " + progress);
                    }
    
                    @Override
                    public void onCompleted() {
                        Log.i(Configurations.TAG, "onCompleted()");
                        exportMp4ToGallery(getApplicationContext(), tempVideoPath);
                        Log.i(Configurations.TAG, "SAVED VIDEO PATH: " + tempVideoPath);
    
                        File file = new File(tempVideoPath);
                        file.delete();
                    }
    
                    @Override
                    public void onCanceled() {
    
                    }
    
                    @Override
                    public void onFailed(Exception e) {
                        Log.i(Configurations.TAG, "onFailed(): " + e.getMessage());
                    }
                })
                .start();
    }
    
    public static void exportMp4ToGallery(Context context, String filePath) {
        final ContentValues values = new ContentValues(2);
        values.put(MediaStore.Video.Media.MIME_TYPE, "video/mp4");
        values.put(MediaStore.Video.Media.DATA, filePath);
        context.getContentResolver().insert(MediaStore.Video.Media.EXTERNAL_CONTENT_URI,
                values);
        context.sendBroadcast(new Intent(Intent.ACTION_MEDIA_SCANNER_SCAN_FILE,
                Uri.parse("file://" + filePath)));
    }
    
    public File getAndroidMoviesFolder() {
        return Environment.getExternalStoragePublicDirectory(Environment.DIRECTORY_PICTURES);
    }
    
    public String getVideoFilePath() {
        return getAndroidMoviesFolder().getAbsolutePath() + "/temp_video.mp4";
    }
    

    【讨论】:

    • 完美 - 但没有“File file = new File(tempVideoPath); file.delete();”
    猜你喜欢
    • 1970-01-01
    • 2013-08-17
    • 1970-01-01
    • 2016-02-03
    • 1970-01-01
    • 1970-01-01
    • 2015-06-18
    • 1970-01-01
    • 2015-09-01
    相关资源
    最近更新 更多