【问题标题】:Adding Overlays to Videos export as a video in android在视频中添加叠加层导出为 android 中的视频
【发布时间】:2018-04-14 19:11:32
【问题描述】:

所以我有一个视频,例如。一个赛车视频,我创建了一个覆盖视图(透明的相对布局),其中包括一些与速度和性能相关的进度条现在我需要导出完整的视频,如该视图所示,所以任何人都可以帮助我,我已经完成了 ffmpeg、opencv但没有成功。

Similar Ios Overlay

【问题讨论】:

  • 哪个叠加层?
  • 请出示您的代码。
  • 我不明白这个问题。这就是我得到的......你想导出一个正在屏幕上播放的视频。你用什么播放视频?
  • 我在视频顶部有一个视图我想导出该视频,该视图嵌入在该视频的顶部
  • 这是一个有趣且困难的问题。所有已发布的解决方案都不会按原样工作。解释太详细了,无法放在评论中。您是否尝试过在视图循环之外进行操作。如果覆盖是静态的,那么使用 ffmpeg 命令相对更容易。但是如果覆盖是动态的(例如字幕),那么 ffmpeg 命令就很复杂。除非视频来自实时流,否则在视图循环中执行此操作不是一个实用的解决方案。类似的一个很好的例子是grafika。您可以使用来自您应用的相关部分。

标签: android ffmpeg video-processing android-mediacodec


【解决方案1】:

我认为您可以使用 OpenCV 或 ffmpeg 来完成此任务,但似乎它们可能不是完成此任务的正确工具。 OpenCV 非常适合高级视频处理,并且在底层它使用 ffmpeg 进行解码和编码功能。当您需要支持多种媒体格式时,ffmpeg 非常棒。对于 ffmpeg,您可以尝试将其作为独立进程运行,但这对于权限问题和错误处理来说并不理想。您还可以编写自己的包含 ffmpeg 的 Android NDK API,但这可能需要付出很多努力。假设您需要的输出媒体格式是supported by Android,最简单的方法是使用 Android MediaCodec 库。

查看来自 Google 的 this test code,它展示了如何解码、编辑和编码。您可以将视频文件解码为 SurfaceTexture。对于编辑部分,您将使用 OpenGL ES 进行叠加。叠加图像可以上传到纹理并在视频帧 SurfaceTexture 上绘制。绘制场景后,可以将输出的纹理发送到 MediaCodec 编码器。这一切都可以在导出过程中完成,不一定需要与您的可视视频和透明相对布局相关联。

【讨论】:

    【解决方案2】:

    您将能够使用 opencv org.bytedeco.javacpp 来实现,我使用 FFmpegFrameGrabber 进行乱码帧和 FFmpegFrameRecorder 将此图像记录回具有相同音频编解码器的 mp4。

    需要的依赖:

        compile group: 'org.bytedeco', name: 'javacv', version: '1.4'
        compile group: 'org.bytedeco.javacpp-presets', name: 'opencv', version: '3.4.0-1.4', classifier: 'android-arm'
        compile group: 'org.bytedeco.javacpp-presets', name: 'ffmpeg', version: '3.4.1-1.4', classifier: 'android-arm'
    

    【讨论】:

      【解决方案3】:

      要将视频解码为位图并将位图编码回 mp4 视频,您可以使用jcodec

      SequenceEncoder sequenceEncoder = new SequenceEncoder(new File(pathToSaveVideo));
      

      循环执行这些步骤

      1. 提取视频每一帧的位图
      2. 与叠加位图结合

         Canvas canvas = new Canvas(backgroundBitmap);
         Paint rectpaint = new Paint(Paint.ANTI_ALIAS_FLAG);
         int width = overlayBitmap.getWidth();
         int height = overlayBitmap.getHeight();
         Rect des = new Rect(0, 0, canvas.getWidth(), canvas.getHeight());
         Rect src = new Rect(0, 0, width, height);
         canvas.drawBitmap(overlayBitmap, src, des, rectpaint);
        
      3. 将其编码回视频

        sequenceEncoder.encodeImage(backgroundBitmap);
        

      循环后终于完成编码器

      sequenceEncoder.finish()

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 2014-10-31
        • 2018-12-17
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2020-11-24
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多