当前位置: 首页 > article >正文

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


http://www.kler.cn/a/398532.html

相关文章:

  • springboot企业级项目常用的pom依赖
  • 超全超详细使用SAM进行高效图像分割标注(GPU加速推理)
  • 狼蛛F87Pro键盘常用快捷键的使用说明
  • 效率工具-tig的使用
  • Markdown中输入空格的几种不同方式
  • 第三百二十三节 Java线程教程 - Java同步器
  • 专题二十_动态规划_简单多状态dp问题_买卖股票系列问题_算法专题详细总结
  • 「Qt Widget中文示例指南」如何创建一个窗口标志?(二)
  • Android Framework层介绍
  • 半导体器件与物理篇3 P-N结
  • Redis的Zset在排行榜中应用
  • 【数据结构】树——顺序存储二叉树
  • 面试题1111
  • 使用Kafka实现大规模数据流处理的最佳实践
  • 用哈希表封装myunordered_map/_set--C++
  • LeetCode100之回文链表(234)--Java
  • 药方新解:Spring Boot中药实验管理系统设计
  • 比较TCP/IP和OSI/RM的区别
  • Maven常用打包方式
  • 对接钉钉审批详情
  • FMEA 在新兴技术领域(如量子计算、人工智能芯片等)的应用挑战与机遇
  • linux内核中如何向slab内存分配器申请内存
  • 操作系统启动实验
  • 引领企业未来数字基础架构浪潮,中国铁塔探索超大规模分布式算力
  • 机器学习(贝叶斯算法,决策树)
  • Git与GitLab的企业实战 笔记(尚硅谷)