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

Android应用如何将PNG图像以流形式发送至Ant Media Server

解决方案:Android将自定义PNG图像流推送到Ant Media Server

针对你的需求,提供两种可行的实现方案,均无需依赖摄像头输入,直接使用你生成的PNG字节数组进行推流:

方案一:基于Ant Media Android SDK替换自定义视频源

Ant Media的WebRTC SDK允许替换默认的摄像头捕获源,你可以实现自定义的视频捕获器来推送自己生成的PNG帧:

  1. 实现自定义VideoCapturer
    继承WebRTC的VideoCapturer类,将PNG字节数组转换为WebRTC所需的YUV_420_888格式帧:

    public class CustomPngCapturer implements VideoCapturer {
        private volatile boolean isCapturing;
        private VideoSink videoSink;
        private HandlerThread captureThread;
        private Handler captureHandler;
    
        @Override
        public void initialize(SurfaceTextureHelper surfaceTextureHelper, Context context, VideoSink videoSink) {
            this.videoSink = videoSink;
            captureThread = new HandlerThread("CustomPngCaptureThread");
            captureThread.start();
            captureHandler = new Handler(captureThread.getLooper());
        }
    
        @Override
        public void startCapture(int width, int height, int fps) {
            isCapturing = true;
            // 定时推送帧,按设置的帧率间隔执行
            captureHandler.postDelayed(new Runnable() {
                @Override
                public void run() {
                    if (!isCapturing) return;
                    // 1. 获取你的PNG字节数组
                    byte[] pngBytes = getGeneratedPngBytes();
                    // 2. 转成Bitmap
                    Bitmap bitmap = BitmapFactory.decodeByteArray(pngBytes, 0, pngBytes.length);
                    // 3. 转换为WebRTC支持的VideoFrame
                    VideoFrame frame = convertBitmapToVideoFrame(bitmap);
                    // 4. 推送帧到SDK
                    videoSink.onFrame(frame);
                    // 释放资源
                    frame.release();
                    bitmap.recycle();
                    // 循环执行
                    captureHandler.postDelayed(this, 1000 / fps);
                }
            }, 0);
        }
    
        @Override
        public void stopCapture() {
            isCapturing = false;
            captureThread.quitSafely();
        }
    
        // 补充实现dispose、isScreencast等必要方法
        // ...省略默认实现代码...
    }
    
  2. 替换SDK默认捕获源
    在初始化WebRTCPublisher时,用自定义capturer替代默认摄像头:

    // 创建PeerConnectionFactory
    PeerConnectionFactory factory = PeerConnectionFactory.builder()
            .setVideoDecoderFactory(new DefaultVideoDecoderFactory(rootEglBase.getEglBaseContext()))
            .setVideoEncoderFactory(new DefaultVideoEncoderFactory(rootEglBase.getEglBaseContext(), true, true))
            .createPeerConnectionFactory();
    
    // 创建自定义VideoSource
    VideoSource videoSource = factory.createVideoSource(false);
    CustomPngCapturer capturer = new CustomPngCapturer();
    capturer.initialize(SurfaceTextureHelper.create("CaptureThread", rootEglBase.getEglBaseContext()), context, videoSource.getSink());
    capturer.startCapture(1280, 720, 25); // 设置分辨率和帧率
    
    // 将自定义源绑定到推流器
    webRTCPublisher.setVideoSource(videoSource);
    // 正常启动推流
    webRTCPublisher.publish(streamUrl);
    

方案二:使用RTMP协议直接推流(轻量化)

如果WebRTC集成过于复杂,可以选择RTMP推流,直接将PNG编码为H.264后推送:

  1. PNG转H.264编码
    使用Android的MediaCodec将Bitmap(从PNG字节数组转换而来)编码为H.264帧:

    // 初始化H.264编码器
    MediaCodec codec = MediaCodec.createEncoderByType("video/avc");
    MediaFormat format = MediaFormat.createVideoFormat("video/avc", 1280, 720);
    format.setInteger(MediaFormat.KEY_BIT_RATE, 1000000);
    format.setInteger(MediaFormat.KEY_FRAME_RATE, 25);
    format.setInteger(MediaFormat.KEY_I_FRAME_INTERVAL, 10);
    codec.configure(format, null, null, MediaCodec.CONFIGURE_FLAG_ENCODE);
    codec.start();
    
    // 将PNG字节数组转为Bitmap并输入编码器
    byte[] pngBytes = getGeneratedPngBytes();
    Bitmap bitmap = BitmapFactory.decodeByteArray(pngBytes, 0, pngBytes.length);
    ByteBuffer[] inputBuffers = codec.getInputBuffers();
    int inputBufferIndex = codec.dequeueInputBuffer(-1);
    if (inputBufferIndex >= 0) {
        ByteBuffer inputBuffer = inputBuffers[inputBufferIndex];
        inputBuffer.clear();
        bitmap.copyPixelsToBuffer(inputBuffer);
        codec.queueInputBuffer(inputBufferIndex, 0, inputBuffer.position(), System.nanoTime() / 1000, 0);
    }
    
    // 获取编码后的H.264数据并发送
    MediaCodec.BufferInfo bufferInfo = new MediaCodec.BufferInfo();
    int outputBufferIndex = codec.dequeueOutputBuffer(bufferInfo, 0);
    if (outputBufferIndex >= 0) {
        ByteBuffer outputBuffer = codec.getOutputBuffers()[outputBufferIndex];
        byte[] h264Data = new byte[bufferInfo.size];
        outputBuffer.get(h264Data);
        sendH264FrameToRtmp(h264Data);
        codec.releaseOutputBuffer(outputBufferIndex, false);
    }
    
  2. RTMP推流连接
    使用RTMP客户端库连接Ant Media Server的推流地址(格式为rtmp://你的服务器IP:1935/LiveApp/你的流名称),将编码后的H.264帧按帧率连续发送。

关键注意事项

  • 性能优化:转码、编码操作放在子线程执行,避免阻塞UI;及时回收Bitmap等资源,防止内存泄漏。
  • 帧率控制:保持稳定的推送帧率(如25fps),避免服务器端播放卡顿。
  • 格式兼容:建议使用1280x720、25fps的标准参数测试,确保格式符合Ant Media Server要求。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.25 03:37:17