You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Android视频添加滤镜时报Failed to add the track to the muxer错误如何解决

Android视频滤镜处理Failed to add the track to the muxer问题排查与修复方案

问题根因共性分析

该错误本质是MediaMuxer添加音轨时格式不匹配、时序错误或者资源冲突导致的,仅带音轨的视频处理出错,说明问题完全出在音频轨道的配置、采集、写入时序环节。

排查步骤

  • 核对音频输出格式与MediaMuxer要求的一致性
    检查音频编码器输出的MediaFormat是否符合以下要求:
    • 必须设置KEY_MIME为audio/mp4a-latm
    • 必须正确设置KEY_SAMPLE_RATE、KEY_CHANNEL_COUNT、KEY_BIT_RATE,和原视频提取的音频参数完全匹配,不要硬编码固定值
    • 音频编码器输出的csd-0、csd-1参数是否正确传递给了addTrack的MediaFormat,滤镜处理环节很容易丢失这两个配置参数
  • 检查音轨添加的时序逻辑

    必须严格遵循MediaMuxer的调用时序:先调用addTrack添加所有轨道(视频+音频),再调用start(),之后才能写帧数据,绝对不允许start之后再调用addTrack
    常见时序错误场景:
    视频轨道配置完成就提前调用了muxer.start(),后面音频编码器配置完成再调用addTrack就会直接抛错,偶发崩溃是因为音频编码速度有时候比视频慢,偶尔视频先准备好提前触发了start,有时候音频先准备好就正常,完全匹配你描述的故障现象

  • 检查音频帧写入的格式匹配
    确认写入muxer的音频帧的bufferInfo.presentationTimeUs是严格递增的,不要出现时间戳回退,同时不要把音频编码的原始PCM帧直接写入,必须是编码器输出的编码后AAC数据才可以传给muxer
  • 检查资源释放逻辑
    确认没有重复调用muxer的addTrack、start、stop、release方法,多线程操作muxer时必须加锁,避免不同线程同时操作muxer触发状态异常

针对性修复方案

1. 轨道就绪等待逻辑优化

在Mp4ComposerEngine里添加轨道就绪计数,只有视频轨道、音频轨道(如果原视频有音轨)都准备完成后,才统一调用muxer.addTrack和muxer.start(),示例逻辑如下:

// 新增成员变量
private AtomicInteger readyTrackCount = new AtomicInteger(0);
private final int REQUIRED_TRACK_COUNT; // 初始化时赋值:有音频为2,无音频为1
private final Object muxerLock = new Object();
private AtomicBoolean isMuxerStarted = new AtomicBoolean(false);

// 每个轨道配置完成时调用
private void onTrackReady(MediaFormat format, boolean isVideo) {
    synchronized (muxerLock) {
        if (isVideo) {
            videoTrackIndex = muxer.addTrack(format);
        } else {
            audioTrackIndex = muxer.addTrack(format);
        }
        if (readyTrackCount.incrementAndGet() == REQUIRED_TRACK_COUNT) {
            muxer.start();
            isMuxerStarted.set(true);
            // 唤醒等待写帧的线程
            muxerLock.notifyAll();
        }
    }
}

// 写帧前先判断muxer是否已经启动,没启动就等待
private void writeSampleData(boolean isVideo, ByteBuffer buffer, MediaCodec.BufferInfo info) {
    synchronized (muxerLock) {
        while (!isMuxerStarted.get()) {
            try {
                muxerLock.wait(10);
            } catch (InterruptedException e) {
                Thread.currentThread().interrupt();
                return;
            }
        }
        int trackIndex = isVideo ? videoTrackIndex : audioTrackIndex;
        muxer.writeSampleData(trackIndex, buffer, info);
    }
}

2. 音频参数适配优化

不要硬编码音频输出参数,完全从原视频的音频轨道提取参数传给音频编码器:

// 提取原音频参数示例
MediaFormat audioFormat = extractor.getTrackFormat(audioTrackIndex);
int sampleRate = audioFormat.getInteger(MediaFormat.KEY_SAMPLE_RATE);
int channelCount = audioFormat.getInteger(MediaFormat.KEY_CHANNEL_COUNT);
int bitRate = audioFormat.containsKey(MediaFormat.KEY_BIT_RATE) ? 
    audioFormat.getInteger(MediaFormat.KEY_BIT_RATE) : 128000;

// 配置音频编码器
MediaCodec audioEncoder = MediaCodec.createEncoderByType("audio/mp4a-latm");
MediaFormat outputAudioFormat = MediaFormat.createAudioFormat("audio/mp4a-latm", sampleRate, channelCount);
outputAudioFormat.setInteger(MediaFormat.KEY_BIT_RATE, bitRate);
outputAudioFormat.setInteger(MediaFormat.KEY_AAC_PROFILE, MediaCodecInfo.CodecProfileLevel.AACObjectLC);
audioEncoder.configure(outputAudioFormat, null, null, MediaCodec.CONFIGURE_FLAG_ENCODE);

3. 多线程操作加锁

所有对MediaMuxer的操作(addTrack、start、writeSampleData、stop、release)都必须加同一把锁,避免多线程并发操作导致状态异常。


内容的提问来源于stack exchange,提问作者S_i_l_e_n_t C_o_d_e_r

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.09.25 03:36:08