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

JavaFX中如何显示MJPEG摄像头URL视频?

在JavaFX中显示MJPEG摄像头流的解决方案

你遇到的问题其实很常见——JavaFX自带的Media和MediaPlayer并不支持MJPEG格式的流媒体,它们主要针对标准封装的视频格式(比如MP4、FLV这类),所以直接用你的代码加载MJPEG URL是不会有任何显示的。

下面给你两种可行的实现方案:

方案一:手动解析MJPEG流(推荐,无第三方依赖)

MJPEG本质是连续的JPEG图片通过HTTP流传输,我们可以通过HTTP请求获取流,解析出每一帧的JPEG数据,然后更新JavaFX的ImageView来实现播放效果。

核心思路:

  • 用HttpClient发起GET请求获取MJPEG流
  • 在后台线程中解析流,识别每一帧的边界(MJPEG通常用--boundary分隔帧)
  • 把解析出的JPEG字节转换成JavaFX的Image
  • 在JavaFX主线程中更新ImageView的内容(避免UI阻塞)

示例代码:

import javafx.application.Platform;
import javafx.scene.image.Image;
import javafx.scene.image.ImageView;
import java.io.ByteArrayInputStream;
import java.io.InputStream;
import java.net.http.HttpClient;
import java.net.http.HttpRequest;
import java.net.http.HttpResponse;
import java.util.concurrent.Executors;

public class MjpegViewer {
    private final ImageView imageView;
    private final String mjpegUrl;
    private volatile boolean running = true;

    public MjpegViewer(ImageView imageView, String mjpegUrl) {
        this.imageView = imageView;
        this.mjpegUrl = mjpegUrl;
        startStreaming();
    }

    private void startStreaming() {
        Executors.newSingleThreadExecutor().submit(() -> {
            HttpClient client = HttpClient.newHttpClient();
            HttpRequest request = HttpRequest.newBuilder()
                    .uri(java.net.URI.create(mjpegUrl))
                    .build();

            try {
                HttpResponse<InputStream> response = client.send(request, HttpResponse.BodyHandlers.ofInputStream());
                InputStream inputStream = response.body();
                byte[] buffer = new byte[8192];
                int bytesRead;
                ByteArrayInputStream frameStream = new ByteArrayInputStream(new byte[0]);

                while (running && (bytesRead = inputStream.read(buffer)) != -1) {
                    // 拼接当前读取的字节到帧流
                    byte[] newBuffer = new byte[frameStream.available() + bytesRead];
                    frameStream.read(newBuffer, 0, frameStream.available());
                    System.arraycopy(buffer, 0, newBuffer, frameStream.available(), bytesRead);
                    frameStream = new ByteArrayInputStream(newBuffer);

                    // 检查是否包含帧边界(替换为你的MJPEG实际边界,可从响应头Content-Type获取)
                    String content = new String(newBuffer);
                    if (content.contains("--boundary")) {
                        // 提取JPEG帧数据
                        int startIndex = content.indexOf("\r\n\r\n") + 4;
                        int endIndex = content.indexOf("--boundary");
                        if (startIndex != -1 && endIndex != -1) {
                            byte[] frameData = new byte[endIndex - startIndex];
                            System.arraycopy(newBuffer, startIndex, frameData, 0, frameData.length);
                            // 在JavaFX主线程更新ImageView
                            Platform.runLater(() -> {
                                Image image = new Image(new ByteArrayInputStream(frameData));
                                imageView.setImage(image);
                            });
                            // 重置帧流,保留边界之后的内容
                            frameStream = new ByteArrayInputStream(newBuffer, endIndex, newBuffer.length - endIndex);
                        }
                    }
                }
            } catch (Exception e) {
                e.printStackTrace();
            }
        });
    }

    public void stopStreaming() {
        running = false;
    }
}

使用方式:

把FXML中的MediaView替换为ImageView,然后在控制器中初始化:

@FXML private ImageView mjpegImageView;

// 初始化时调用
new MjpegViewer(mjpegImageView, "http://192.165.96.36/mjpg/video.mjpg");

方案二:使用第三方库

如果不想自己处理流解析,可以使用支持MJPEG的JavaFX第三方组件(比如部分开源的流媒体工具类),但这种方式会增加项目依赖,需要根据需求权衡。

关键注意事项:

  • 务必替换代码中的--boundary为你的MJPEG流实际分隔符,可通过浏览器访问URL查看响应头的Content-Type字段(格式类似multipart/x-mixed-replace; boundary=xxx)
  • 后台线程要妥善关闭资源,避免内存泄漏
  • 如果摄像头需要认证,要在HTTP请求中添加对应的认证头

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.05.27 09:24:04