自学内容网 自学内容网

Android 关于使用videocompressor库压缩没有声音和异常的问题

原库地址

https://gitcode.com/gh_mirrors/vi/VideoCompressor/overview
这个库用起来比较方便,使用Android原生的MediaCodec+mp4parser的方式进行压缩,不用接入so库也不用适配cpu

问题

接口库后你会发现过时了,所以你一阵捣鼓后你发现压缩正常但是输出文件没有声音,问题是什么?经过我一天的修改,问题是因为你升级了mp4parser库他接入的是com.googlecode.mp4parser:isoparser:1.0.6不论你升级到什么版本都会出现没有声音的问题,那是因为谷歌的问题,在1.0.6后在编码的时候更加严格,所以你不升级就ok了!

真的不升级?

随着时间的发展旧版本库无法满足需求,性能各方面都是差异,而且这是7年前的库了,所以你必须升级,那么怎么解决问题呢?

分析问题

问题代码

在1.0.6库之前和之后主要的出现问题代码就在createMovie中的创建FileChannel的问题,1.0.6支持你FileOutputStream.getChannel()这样创建但是1.0.6之后不可以这样,这样就会导致音视频无法同步,所以你需要更换创建方法:new RandomAccessFile(destinationPath, "rw").getChannel()其中destinationPath输出文件地址修改了这一行你会发现好了

其他解决思路

这个库的压缩思路:

  1. 获取视频的track,然后利用MediaCodec对原视频进行解码

  2. 获取原视频的宽高、帧率等,进行一定的比例缩放

  3. 在利用MediaCodec进行视频编码,输出一个只有视频没有声音的文件

  4. 在利用相同的方式获取音频的track,然后读取音频读写

  5. 最后对音视频进行合并,他是再同一个输出文件上读写的

  6. 完结
    所以根据上面思路你完全可以分开

  7. 先利用MediaCodec对视频进行压缩,输出到缓存目标文件A

  8. 在读取原文件的音频

  9. 合并两个文件,输出到真正的目录B,这里不可以和缓存目标文件A相同,必须不同的文件

把思路简化下代码大概是这样,是不是很简单,其实思路就这么点代码

    public static void appendMp4List(Context context, Uri sourcePath, String outPutPath) throws Exception {
        VideoInfo videoInfo = VideoUtils.getVideoInfo(context, sourcePath);
        if (videoInfo == null || videoInfo.width() == 0 || videoInfo.height() == 0) {
            return;
        }
        File tempFile = VideoUtils.copyFileToCacheDir(context, sourcePath);
        List<Track> audioTracks = new LinkedList<>();// 音频通道集合
        List<Track> videoTracks = new LinkedList<>();// 视频通道集合

        for (Track inMovieTrack : MovieCreator.build(tempFile.getAbsolutePath()).getTracks()) {
            if ("soun".equals(inMovieTrack.getHandler())) {// 从Movie对象中取出音频通道
                audioTracks.add(inMovieTrack);
            }
            if ("vide".equals(inMovieTrack.getHandler())) {// 从Movie对象中取出视频通道
                videoTracks.add(inMovieTrack);
            }
        }

        Movie resultMovie = new Movie();// 结果Movie对象[输出]
        if (!videoTracks.isEmpty()) {// 将所有视频通道追加合并
            writerVideo(tempFile,videoInfo,outPutPath);//压缩视频,但这样输出的只有视频没有音频
            List<Track> resultVideoTrack = MovieCreator.build(outPutPath).getTracks();
            for(Track videoTrack:resultVideoTrack){
                resultMovie.addTrack(videoTrack);
            }
        }
        if (!audioTracks.isEmpty()) {// 将所有音频通道追加合并
            resultMovie.addTrack(new AppendTrack(audioTracks.toArray(new Track[audioTracks.size()])));
        }
        Container outContainer = new DefaultMp4Builder().build(resultMovie);// 将结果Movie对象封装进容器
        FileChannel fileChannel = new RandomAccessFile(outPutPath, "rw").getChannel();
        outContainer.writeContainer(fileChannel);// 将容器内容写入磁盘
        fileChannel.close();
    }

最终的优化有的代码查看github

https://github.com/fzkf9225/mvvm-componnent-master/tree/master/commonmedia/src/main/java/pers/fz/media/videocompressor


原文地址:https://blog.csdn.net/fzkf9225/article/details/143777865

免责声明:本站文章内容转载自网络资源,如本站内容侵犯了原著者的合法权益,可联系本站删除。更多内容请关注自学内容网(zxcms.com)!