标签: mediamuxer

使用MediaCodec和MediaMuxer对视频进行编码和复用

我正在开发一个应用程序,我解码视频并替换某些帧并使用MediaMuxer和重新编码MediaCodec.如果我不替换任何帧(除了1080p视频,我将在下面解释),该应用程序可以工作,但是当我这样做时,替换后的帧会像素化,视频会不稳定.

此外,当我尝试使用1920x1080视频的应用程序时,我得到一个奇怪的输出,其中视频没有显示任何内容,直到我滚动到视频的开头,然后视频开始显示(但具有之前提到的相同问题)编辑后的像素化.

以下是我配置编码器的方法:

Video_format.setInteger(MediaFormat.KEY_I_FRAME_INTERVAL, interval);
Video_format.setInteger(MediaFormat.KEY_BIT_RATE, bitRate);
Video_format.setInteger(MediaFormat.KEY_FRAME_RATE, frameRate);
Video_format.setInteger(MediaFormat.KEY_MAX_INPUT_SIZE, 0);
int color_format=MediaCodecInfo.CodecCapabilities.COLOR_FormatYUV420SemiPlanar;
Video_format.setInteger(MediaFormat.KEY_COLOR_FORMAT, color_format);

encoder.configure(Video_format, null, null, MediaCodec.CONFIGURE_FLAG_ENCODE);
Run Code Online (Sandbox Code Playgroud)

总而言之,我有两个问题:

1-修改帧后的像素化帧和不连贯的视频.

2-损坏的1920x1080视频,除非我滚动到开头.

编辑

这是一个未经编辑的1080p视频示例,当我在VLC上播放并在手机上播放不正确时会显示绿屏,除非我滚动开始,现在奇怪地在YouTube上正常工作,除了开始时的绿框

这是一个720p视频样本,在开始时也使用绿色框架进行编辑,并在编辑后清除像素化和滞后

这是我用来解码重新编码的代码:

do{
  Bitmap b1;

  if(edited_frames.containsKey(extractor.getSampleTime()))
    b1=BitmapFactory.decodeFile(edited_frames.get(extractor.getSampleTime()));
  else
    b1=decode(extractor.getSampleTime(),Preview_width,Preview_Height);

  if(b1==null) continue;

  Bitmap b_scal=Bitmap.createScaledBitmap(b1, Preview_width, Preview_Height, false);
  if(b_scal==null) continue;
  encode(b_scal, encoder, muxer, videoTrackIndex);
  lastTime=extractor.getSampleTime();
}while(extractor.advance());
Run Code Online (Sandbox Code Playgroud)

解码方法:

private Bitmap decode(final long time,final int width,final int height){
  MediaFormat newFormat = codec.getOutputFormat();
  Bitmap b = null;
  final int TIMEOUT_USEC = 10000;
  ByteBuffer[] …
Run Code Online (Sandbox Code Playgroud)

video android mediacodec mediamuxer

61
推荐指数
1
解决办法
6672
查看次数

在android中添加水印位图:4.3的MediaMuxer或ffmpeg

这是我的场景:

  • 从网上下载avi电影
  • 打开位图资源
  • 在背景中的所有帧上将此位图叠加在电影的底部
  • 将视频保存在extarnal存储上
  • 视频长度通常为15秒

这可能是使用MediaMuxer实现的吗?很高兴收到有关此事的任何信息

我一直在寻找http://bigflake.com/mediacodec/#DecodeEditEncodeTest(谢谢@fadden),它说:

"解码帧并将其复制到ByteBuffer, glReadPixels()在Nexus 5上大约需要8ms,足够快,足以跟上30fps的输入速度,但将其作为PNG保存到磁盘所需的额外步骤是昂贵的(大约半秒钟) "

所以几乎1秒/帧是不可接受的.根据我的想法,一种方法是将每个帧保存为PNG,打开它,在其上添加位图叠加然后保存它.然而,这将花费大量时间来完成.

我想知道是否有办法做这样的事情:

  1. 从外部存储打开视频文件
  2. 开始解码它
  3. 每个解码的帧将被改变,内存中的位图覆盖
  4. 帧被发送到编码器.

在iOS上,我看到有一种方法可以将原始音频+原始视频+图像添加到容器中,然后对整个事物进行编码...

我应该切换到ffmpeg吗?ffmpeg的稳定性和兼容性如何?我是否冒着与Android 4.0+设备兼容的问题?有没有办法用ffmpeg来实现这个?我是这个领域的新手,还在做研究.


多年后编辑:
自问题以来已过去多年,并且ffmpeg在许可方面很难添加到商业软件中.这是如何演变的?较新版本的android在默认sdk上更有能力吗?


稍后编辑一段时间

我发布了一些负面投票信息作为答案,因此我将编辑原始问题.这是一个很棒的库,从我的测试中确实将水印应用于视频并使用进度回调进行处理,这使得向用户显示进度变得更加容易,并且还使用默认的android sdks.https://github.com/MasayukiSuda/Mp4Composer-android

该库使用Android MediaCodec API生成Mp4电影,并应用滤镜,缩放和旋转Mp4.

示例代码,可能如下所示:

new mp4Composer(sourcePath, destinationPath)
        .filter(new GlWatermarkFilter(watermarkBitmap)
        .listener(){
              @Override 
              private void onProgress(double value){}

              @Override 
              private void onCompleted(double value){
                  runOnUiThread( () ->{
                     showSneakbar
                  }
              }

              @Override 
              private void onCancelled(double value){}

              @Override 
              private void onFailed(Exception e){}

        }).start();
Run Code Online (Sandbox Code Playgroud)

在模拟器上进行测试,似乎在android 8+上正常工作,而在旧版本上生成黑色视频文件.但是,在真实设备上进行测试似乎有效.

mp4 android ffmpeg mediacodec mediamuxer

31
推荐指数
3
解决办法
1万
查看次数

我怎样才能修剪Uri的视频,包括`mp4parser`库可以处理的文件,而是使用Android的框架呢?

背景

在过去的几年里,我一直在做的视频修剪库的定制,更多更新的版本的工作,在这里(基于这个库)

问题

虽然在大多数情况下,我已经成功地将其定制,甚至将所有文件转换为Kotlin,但它在修剪本身时遇到了一个重大问题.

它假定输入始终是文件,因此如果用户从返回Uri的应用选择器中选择一个项目,它就会崩溃.这样做的原因不仅仅是UI本身,还因为它用于修剪的库(mp4parser)假定只输入File(或文件路径)而不是Uri(在此处写过).我尝试了多种方法来让它获得一个Uri,但失败了.还在这里写了一下.

这就是为什么我使用我在StackOverflow(这里)找到的解决方案进行修剪的原因.关于它的好处是它很安静,只使用Android的框架本身.但是,似乎对于某些视频文件,它总是无法修剪它们.由于这些文件的一个例子,有一个原始库的储存库,在这里(问题报道这里).

看看异常,这就是我得到的:

E: Unsupported mime 'audio/ac3'
E: FATAL EXCEPTION: pool-1-thread-1
    Process: life.knowledge4.videocroppersample, PID: 26274
    java.lang.IllegalStateException: Failed to add the track to the muxer
        at android.media.MediaMuxer.nativeAddTrack(Native Method)
        at android.media.MediaMuxer.addTrack(MediaMuxer.java:626)
        at life.knowledge4.videotrimmer.utils.TrimVideoUtils.genVideoUsingMuxer(TrimVideoUtils.kt:77)
        at life.knowledge4.videotrimmer.utils.TrimVideoUtils.genVideoUsingMp4Parser(TrimVideoUtils.kt:144)
        at life.knowledge4.videotrimmer.utils.TrimVideoUtils.startTrim(TrimVideoUtils.kt:47)
        at life.knowledge4.videotrimmer.BaseVideoTrimmerView$initiateTrimming$1.execute(BaseVideoTrimmerView.kt:220)
        at life.knowledge4.videotrimmer.utils.BackgroundExecutor$Task.run(BackgroundExecutor.java:210)
        at java.util.concurrent.Executors$RunnableAdapter.call(Executors.java:458)
        at java.util.concurrent.FutureTask.run(FutureTask.java:266)
        at java.util.concurrent.ScheduledThreadPoolExecutor$ScheduledFutureTask.run(ScheduledThreadPoolExecutor.java:301)
        at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1167)
        at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:641)
        at java.lang.Thread.run(Thread.java:764)
Run Code Online (Sandbox Code Playgroud)

我发现了什么

  1. 这里报道了这个问题.我不认为它会得到答案,因为图书馆多年来没有更新......
  2. 看着异常,我试着在没有声音的情况下修剪.这有效,但这不是一件好事,因为我们想要正常修剪.
  3. 认为这段代码可能基于别人的代码,我试图找到原始代码.我发现它基于其图库应用程序中的一些旧的Google代码,在此处 …

android video-editing mediamuxer

15
推荐指数
1
解决办法
450
查看次数

MediaMuxer无法制作可流式传输的MP4

我在Android上使用MediaExtractor编辑MP4来获取音频和视频曲目,然后使用MediaMuxer创建新文件.它工作正常.我可以在手机(和其他播放器)上播放新的MP4,但无法在网络上传输文件.当我停止MediaMuxer时,它会生成一条日志消息

"mp4文件不会流式传输."

我查看了底层的本机代码(MPEG4Writer.cpp),看起来编写器在计算所需的moov盒大小时遇到​​了麻烦.如果没有将比特率作为参数提供给作者,它会尝试使用某种启发式进行猜测.问题是MediaMuxer无法提供设置MPEG4Writer参数的功能.我是否遗漏了某些东西,或者我是不是在寻找其他一些生成文件(或标题)的方法?谢谢.

video android mediaextractor mediamuxer

8
推荐指数
1
解决办法
2604
查看次数

MediaMuxer视频文件大小减小(重新压缩,降低分辨率)

我正在寻找有效的方法来减少一些视频权重(作为File上传),明显的答案是:让我们降低分辨率!(全高清或4K不需要,简单的高清对我来说已经足够了)我已经尝试了很多方法应该通过很多API(需要10),最好的方法是使用android-ffmpeg-java,但是...我的漂亮快速几乎当前的旗舰设备整个过程持续约length_of_video*4秒,此lib的重量是9 Mb,这个数量增加了我的应用程序大小...没有wai!(12 Mb到1 Mb是很好的结果,但仍然有太多的缺陷)

所以我决定使用原生的Android方式来实现这一点,MediaMuxer并且MediaCodec- 它们分别来自API18和API16(旧设备用户:抱歉;但他们也经常使用"低分辨率"相机).下面的方法几乎可以工作 - MediaMuxer不尊重MediaFormat.KEY_WIDTHMediaFormat.KEY_HEIGHT- 提取File是"重新压缩",重量稍微小一点,但分辨率与原始视频相同File...

那么,问题:如何使用MediaMuxer和其他随附的类和方法压缩和重新调整/更改视频的分辨率?

public File getCompressedFile(String videoPath) throws IOException{
    MediaExtractor extractor = new MediaExtractor();
    extractor.setDataSource(videoPath);
    int trackCount = extractor.getTrackCount();

    String filePath = videoPath.substring(0, videoPath.lastIndexOf(File.separator));
    String[] splitByDot = videoPath.split("\\.");
    String ext="";
    if(splitByDot!=null && splitByDot.length>1)
        ext = splitByDot[splitByDot.length-1];
    String fileName = videoPath.substring(videoPath.lastIndexOf(File.separator)+1,
                    videoPath.length());
    if(ext.length()>0)
        fileName=fileName.replace("."+ext, "_out."+ext);
    else
        fileName=fileName.concat("_out");

    final File outFile = new File(filePath, …
Run Code Online (Sandbox Code Playgroud)

video android video-processing mediacodec mediamuxer

7
推荐指数
2
解决办法
7863
查看次数

android - 如何复用音频文件和视频文件?

我有一个从麦克风录制的3gp文件和一个mp4视频文件.我想将音频文件和视频文件复制到mp4文件并保存.我搜索了很多,但没有找到任何有助于使用Android的MediaMuxer api的东西. MediaMuxer api

更新:这是我的方法,mux两个文件,我有一个例外.原因是目标mp4文件没有任何轨道!someOne可以帮助我添加音频和视频轨道到多路复用器?

例外

java.lang.IllegalStateException: Failed to stop the muxer
Run Code Online (Sandbox Code Playgroud)

我的代码:

private void cloneMediaUsingMuxer( String dstMediaPath) throws IOException {
    // Set up MediaExtractor to read from the source.
    MediaExtractor soundExtractor = new MediaExtractor();
    soundExtractor.setDataSource(audioFilePath);
    MediaExtractor videoExtractor = new MediaExtractor();
    AssetFileDescriptor afd2 = getAssets().openFd("Produce.MP4");
    videoExtractor.setDataSource(afd2.getFileDescriptor() , afd2.getStartOffset(),afd2.getLength());


    //PATH
    //extractor.setDataSource();
    int trackCount = soundExtractor.getTrackCount();
    int trackCount2 = soundExtractor.getTrackCount();

    //assertEquals("wrong number of tracks", expectedTrackCount, trackCount);
    // Set up MediaMuxer for the destination.
    MediaMuxer muxer;
    muxer = new MediaMuxer(dstMediaPath, MediaMuxer.OutputFormat.MUXER_OUTPUT_MPEG_4);
    // Set …
Run Code Online (Sandbox Code Playgroud)

video android mediamuxer

7
推荐指数
1
解决办法
1万
查看次数

Android提取解码编码Mux音频

我正在尝试调整ExtractDecodeEditEncodeMuxTest.java中的代码,以便从通过Cordova的device.capture.captureVideo录制的mp4中提取音频和视频,解码音频,编辑解码的音频样本,编码音频,并将音频复用回来用视频再次保存为mp4.

我的第一次尝试只是提取,解码,编码和复用音频而不尝试编辑任何音频样本 - 如果我能做到这一点,我相当确定我可以根据需要编辑解码的样本.我不需要编辑视频,因此我假设我可以简单地使用MediaExtractor来提取和复用视频轨道.

但是,我遇到的问题是我似乎无法正确地获得音频解码/编码过程.不断发生的事情是,复用器从提取的视频轨道和提取的 - >解码 - >编码的音频轨道创建mp4,但是当视频播放正常时,音频以短暂的噪声开始,然后看起来像是最后一个几秒钟的音频数据正常播放(但在视频的开头),然后静音播放视频的其余部分.

一些相关领域:

private MediaFormat audioFormat;
private MediaFormat videoFormat;
private int videoTrackIndex = -1;
private int audioTrackIndex = -1;
private static final int MAX_BUFFER_SIZE = 256 * 1024;

// parameters for the audio encoder
private static final String OUTPUT_AUDIO_MIME_TYPE = "audio/mp4a-latm"; // Advanced Audio Coding
private static final int OUTPUT_AUDIO_CHANNEL_COUNT = 2; // Must match the input stream. not using this, getting from input format
private static final int OUTPUT_AUDIO_BIT_RATE = …
Run Code Online (Sandbox Code Playgroud)

audio android multiplexing mediacodec mediamuxer

7
推荐指数
1
解决办法
2103
查看次数

使用MediaCodec和MediaMuxer录制视频,但码率和帧率不正确

我写了一个演示来使用 MediaCodec 和 MediaMuxer 录制视频。

我用我的demo录制了一段视频,用ffprobe查看视频,结果如下:

  Duration: 00:00:06.86, start: 0.000000, bitrate: 723 kb/s
Stream #0:0(eng): Video: h264 (High) (avc1 / 0x31637661), yuv420p, 320x240, 619 kb/s, SAR 1:1 DAR 4:3, 30.02 fps, 30 tbr, 90k tbn, 180k tbc (default)
Metadata:
  creation_time   : 2015-06-05 13:19:24
  handler_name    : VideoHandle
Stream #0:1(eng): Audio: aac (LC) (mp4a / 0x6134706D), 44100 Hz, mono, fltp, 96 kb/s (default)
Metadata:
  creation_time   : 2015-06-05 13:19:24
  handler_name    : SoundHandle
Run Code Online (Sandbox Code Playgroud)

它包含视频和音频信息,我发现音频属性与我在源代码中设置的相同,但视频属性不正确。我的视频设置源码如下:

        MediaFormat format = MediaFormat.createVideoFormat(MIME_TYPE, mWidth, mHeight);
    format.setInteger(MediaFormat.KEY_COLOR_FORMAT,
            MediaCodecInfo.CodecCapabilities.COLOR_FormatSurface);
    format.setInteger(MediaFormat.KEY_BIT_RATE, 384000); …
Run Code Online (Sandbox Code Playgroud)

android bitrate mediamuxer android-mediacodec

6
推荐指数
1
解决办法
6047
查看次数

Android MediaCodec dequeueInputBuffer 总是返回 -1

我正在尝试从 AudioRecord 对象中获取原始数据,并使用 MediaMuxer 和 MediaCodec 将其保存在文件中。

我启动编解码器,启动多路复用器,将数据加载到输入缓冲区中,但没有这样的运气。

从调试调查中,我发现问题发生在对dequeueInputBuffer(). 看起来前几块数据成功了,但最终dequeueInputBuffer()只是-1不断返回。

有什么明显的东西我失踪了吗?这似乎是我正在填满输入缓冲区,但编解码器永远不会释放它们。

相关代码片段:

int numChunks = input.length / CHUNKSIZE;
mAudioEncoder.start();
    for (int chunk = 0; chunk <= numChunks; chunk++) {
        byte[] passMe = new byte[CHUNKSIZE];
        int inputBufferIndex = -1;
        Log.d("offerAudioEncoder","printing chunk #" + chunk + "of " + numChunks);
        //Copy the data into the chunk array
        if (chunk < input.length / CHUNKSIZE)
            for (int i = 0; i < CHUNKSIZE; i++)
                passMe[i] = input[chunk * …
Run Code Online (Sandbox Code Playgroud)

audio encoding android mediamuxer android-mediacodec

6
推荐指数
1
解决办法
1758
查看次数

使用媒体投影 API 在设备之间共享屏幕

我正在开发一个具有与其他应用程序共享屏幕功能的应用程序。

我为此使用了媒体投影 API。我还使用 MediaMuxer 组合音频和视频输出以进行屏幕共享。

我知道媒体投影 API 用于屏幕录制,但我只想在录制时共享屏幕。

为此,我修改了 MediaMuxer 类的 writeSampleData 方法,以通过套接字将字节发送到网络上的其他设备。

下面是代码:

OutputStream outStream;
Run Code Online (Sandbox Code Playgroud)

outStream = ScreenRecordingActivity.getInstance().socket.getOutputStream();

void writeSampleData(final int trackIndex, final ByteBuffer byteBuf, final MediaCodec.BufferInfo bufferInfo) {
    if (mStatredCount > 0) {
        mMediaMuxer.writeSampleData(trackIndex, byteBuf, bufferInfo);

        if (bufferInfo.size != 0) {

            byteBuf.position(bufferInfo.offset);
            byteBuf.limit(bufferInfo.offset + bufferInfo.size);

            if (outStream != null) {

                try {

                    byte[] bytes = new byte[byteBuf.remaining()];
                    byteBuf.get(bytes);

                    //Send the data
                    outStream.write(bytes);
                    outStream.flush();

                } catch (IOException e) {
                    e.printStackTrace();
                }
            }
        }
    }
}
Run Code Online (Sandbox Code Playgroud)

字节通过套接字成功传输,我也能够在接收器端接收这些字节。

下面是接收端接收字节的代码:

private class …
Run Code Online (Sandbox Code Playgroud)

android mediamuxer android-mediaprojection android-mediacodec

6
推荐指数
1
解决办法
2134
查看次数