利用 Web 浏览器构建 Java Media Player

news2024/9/21 0:29:52

如果您需要在 Java 桌面应用程序中嵌入媒体播放器,有几种方法可供选择:

  • 您可以使用 JavaFX Media API 来实现所有必需的媒体播放器功能。
  • 虽然稍显过时但仍然可用的 Java Media Framework 也可以作为一种解决方案。
  • 您可以集成像 VLCJ 这样的第三方 Java 库,它封装了本机媒体播放器的功能。

每种方法都有其优缺点:

JavaFX Media API 方法是跨平台的,适用于 Windows、Linux 和 macOS。它在 JavaFX 中运作良好。但是,如果您使用 Swing 或 SWT,则需要诸如 JFXPanelFXCanvas 这样的桥接器。

封装本机媒体播放器的功能需要为每个平台单独进行配置,因为播放器可能不支持所有必需的平台。例如,VLCJ 就不支持 Linux。此外,您可能还需要在目标平台上安装缺失的视频和音频编解码器,以播放各种媒体格式。

利用 Web 浏览器的功能

如今,我们大部分的媒体内容都是通过 Web 浏览器来获取的。它们适用于多个平台,并且支持播放各种音频和视频格式。同时,还具备播放媒体内容所需的所有必要功能。既然 Web 浏览器已经如此强大和全面,我们为何不考虑在 Java 桌面应用程序中利用这一优势来播放媒体内容呢?

在本文中,我将介绍另一种可在 Java Swing、JavaFX 或 SWT 应用程序中构建跨平台 Java 媒体播放器的方法。具体操作如下:

  1. 使用 JxBrowser[1] 将 Web 浏览器控件集成到简单的 Java Swing 应用程序中。
  2. 利用 HTML5 的功能加载用于播放所需视频的 HTML 网页。
  3. 通过直接从 Java 代码中调用的 JavaScript 命令来控制视频的播放。

JxBrowser 是一款商业 Java 库,它允许您在跨平台的 Java Swing、JavaFX 和 SWT 应用程序中充分利用 Chromium 的强大功能。非常适合那些基于 Java 技术开发并销售软件解决方案的公司使用。

过去,Flash Player 是我们在网页上展示各种媒体内容的常用工具,备受欢迎。然而,随着技术的不断发展,2020 年 12 月,Flash Player 正式退出了历史舞台,现在,HTML5 的 Video 和 Audio API 已经全面取代了它的地位。

目前,我们主要有两种方式来利用这些 API 播放媒体内容:

  1. 直接使用 HTML5 的 Video 和 Audio API 进行操作。
  2. 使用第三方 JavaScript 库,如 Plyr、Video.js 等。

在本文中,我将使用 Plyr 库 — 这个最受欢迎的 HTML5 媒体播放器之一。它简单易用,与应用程序集成起来非常方便。

实现

让我们创建一个演示程序,展示如何使用 Plyr JS 库和 JxBrowser 构建跨平台的 Java 媒体播放器。

首先,我们需要创建一个 HTML 页面(media.html),其中包含 JS 库,嵌入视频播放器,并配置目标 MP4 视频文件的位置:

<!DOCTYPE html>
<html lang="en">
<head>
  <meta charset="UTF-8">
  <title>Java Media Player</title>
  <link rel="stylesheet" href="<https://cdn.plyr.io/3.6.8/plyr.css>"/>
</head>
<body style="margin:0">

<video id="player"
       controls
       crossorigin
       playsinline
       data-poster="<https://cdn.plyr.io/static/demo/View_From_A_Blue_Moon_Trailer-HD.jpg>">
  <source src="<https://cdn.plyr.io/static/demo/View_From_A_Blue_Moon_Trailer-720p.mp4>"
          type="video/mp4"/>
</video>

<script src="<https://cdn.plyr.io/3.6.8/plyr.js>" crossorigin="anonymous"></script>
</body>
</html>

接下来,我们需要创建一个简单的 Java Swing 应用程序,该程序将显示一个带有 Web 浏览器和播放控件的 JFrame 窗口:

JFrame frame = new JFrame("Java Media Player");
frame.add(new MediaPlayer(), BorderLayout.CENTER);
frame.setVisible(true);

MediaPlayer 组件包含了 Web 浏览器和播放控件。它具有以下初始化逻辑:

engine = Engine.newInstance(
        EngineOptions.newBuilder(HARDWARE_ACCELERATED)
                // 在这个演示中,我们加载了 MP4 视频文件,
                // 因此我们必须启用默认情况下禁用的相应专有功能。
                .enableProprietaryFeature(ProprietaryFeature.H_264)
                .enableProprietaryFeature(ProprietaryFeature.AAC)
                // 启用通过 JavaScript 在网页上无需用户交互即可编程播放视频的功能。
                .enableAutoplay()
                .build());
Browser browser = engine.newBrowser();

// 将 JsPlayer 的实例注入到 JavaScript 中,
// 以便从 JavaScript 中调用其方法来通知播放器事件。
browser.set(InjectJsCallback.class, params -> {
    Frame frame = params.frame();
    JsObject window = frame.executeJavaScript("window");
    if (window != null) {
        player = new JsPlayer(frame);
        window.putProperty("java", player);
    }
    return Response.proceed();
});

// 获取包含 JS 视频播放器的 media.html 文件的绝对路径,
// 加载该文件并等待其完全加载完成,
// 这样我们就可以构建播放器 UI 控件了。
URL resource = MediaPlayer.class.getResource("/media.html");
if (resource != null) {
    browser.navigation().loadUrlAndWait(resource.toString());
}

// 创建一个可视化 Swing 控件,
// 用于显示包含视频的网页内容。
BrowserView view = BrowserView.newInstance(browser);
view.setPreferredSize(new Dimension(1280, 720));

// 将控件嵌入到 Java Swing 框架中。
setLayout(new BorderLayout());
add(view, BorderLayout.CENTER);
add(playbackControls(), BorderLayout.SOUTH);

让我来解释一下我在初始化逻辑中都做了什么。在上面的代码中,我配置了 Engine 实例,该实例相当于 Google Chrome 应用程序,并为其设置了几个选项:

  • 启用 H264 和 AAC 专有功能,以便能够播放 MP4 视频;
  • 启用通过 JavaScript 在网页上无需用户交互即可编程播放视频的功能。

接下来,我创建了一个 Browser 实例,它相当于 Chrome 浏览器的一个标签页,并加载了 media.html 文件。为了显示 HTML 文件的内容,我创建了一个 Swing BrowserView 控件,并将其嵌入到 Java 框架中。

在演示应用程序中,我决定使用以下媒体播放器功能:

  • 播放和暂停;
  • 静音和取消静音;
  • 调节音量;
  • 获取视频时长(以秒为单位);
  • 当当前播放时间发生变化时接收通知;
  • 设置当前播放时间。

对于上述每一种播放功能,我都创建了一个对应的 Java Swing GUI 控件,以便最终的播放面板具有以下外观:

现在,我需要将这些控件与 JS 媒体播放器的相应功能进行绑定。例如,当我点击播放按钮时,我需要调用 player.play() 这个 JS 函数。为此,我使用了相应的 JxBrowser API:

frame.executeJavaScript("player.play()");

为了从 JavaScript 接收播放状态改变的通知,我需要定义一个公开的 Java 类,并在其中使用 @JsAccessible 注解标记公开方法,如下所示:

public final class JsPlayer {
    @JsAccessible
    public void onTimeUpdated(double currentTime) {
        listeners.forEach(listener -> listener.accept(currentTime));
    }
}

接着,让我们同样使用以下 JxBrowser API 创建该类的一个实例,并将其注入到 JavaScript 中:

browser.set(InjectJsCallback.class, params -> {
    Frame frame = params.frame();
    JsObject window = frame.executeJavaScript("window");
    if (window != null) {
        player = new JsPlayer(frame);
        window.putProperty("java", player);
    }
    return Response.proceed();
});

使用 @JsAccessible 注解的方法在 JavaScript 中是“可见”的,当相应的事件被触发时,可以调用它们。

在该 media.html 文件中,我需要添加 JavaScript 代码,以便在发生不同的播放事件时通知 Java 端:

<script>
  player.on('时间更新', event => {
    java.onTimeUpdated(player.currentTime);
  });
  player.on('音量变化', event => {
    java.onVolumeChanged(player.volume, player.muted);
  });
  player.on('播放', event => { java.onPlaybackStarted(); });
  player.on('暂停', event => { java.onPlaybackPaused(); });
</script>

该程序的完整源代码以及 media.html 文件可在 GitHub[2] 上获取。

结果

如果您编译并运行该程序,您将会看到以下输出:

Java 媒体播放器演示应用程序

JxBrowser 是跨平台的,因此这种方法适用于所有平台,无需您付出额外的努力。

结论

HTML5 的视频功能足以构建自定义媒体播放器,以在各种平台上播放大多数流行的视频和音频格式。

希望本文所述方法能对您有所帮助,也期待收到您的宝贵评论和建议。

参考资料

[1] JxBrowser: https://teamdev.cn/jxbrowser/?utm_campaign=java-media-player&utm_medium=article&utm_source=csdn

[2] GitHub: https://github.com/TeamDev-IP/JxBrowser-Examples/tree/master/tutorials/media-player/src/main?utm_source=csdn&utm_medium=article&utm_campaign=java-media-player

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/2091504.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

统计机器学习基础知识

一、统计机器学习定义 统计机器学习&#xff08;Statistical Machine Learning&#xff09;又称为统计学习&#xff08;Statistical Learning&#xff09;&#xff0c;是关于计算机基于数据构建概率统计模型并运用模型对数据进行预测与分析的一门学科&#xff0c;是概率论、统…

ET6框架(十)通讯消息编写

文章目录 一、消息在的定义&#xff1a;二、客户端消息的发送&#xff1a;三、服务器消息的处理&#xff1a;四、查看结果 一、消息在的定义&#xff1a; ET消息主要分为两类&#xff0c;一个种是普通消息&#xff0c;一种时通过Gate网关转发的消息叫Local消息 这里我们编写客…

【突发事件】Runway删库了,文章结尾有解决方法

最近&#xff0c;Runway 悄悄地从 Hugging Face 平台上删除了自己的代码库&#xff0c;其中包括备受瞩目的 Stable Diffusion v1.5 项目&#xff0c;这在科技界引起了轩然大波。 Runway 的行为不仅没有留下任何痕迹&#xff0c;也没有通知 Hugging Face 或任何社区成员。 更令人…

QEMU - user network

Documentation/Networking - QEMUQEMU/KVM中的网络虚拟化--Part2 User Networking | Xiaoye Zhengs blog (zxxyy.github.io)QEMU Network — ARM SoC Device Assignment Notes documentation (cwshu.github.io)slirp / libslirp GitLabGitHub - virtualsquare/libvdeslirp: li…

运用Premiere自学视频剪辑,这些岗位你能胜任!

随着短视频的兴起和火热&#xff0c;短视频后期制作越来越受到人们的重视&#xff0c;甚至衍生出很多岗位的高薪工作。如大家所了解的&#xff0c;Adobe premiere正是一款视频后期剪辑和制作工具&#xff0c;其功能强大&#xff0c;应用也十分广泛&#xff0c;是从事后期工作者…

【舞动生命,不缺营养!】亨廷顿舞蹈症患者的维生素秘籍✨

Hey小伙伴们&#xff5e;&#x1f44b; 在这个充满色彩的世界里&#xff0c;每个人都是独一无二的舞者&#xff0c;但对于患有亨廷顿舞蹈症的朋友来说&#xff0c;他们的舞蹈却多了几分挑战与不易。&#x1f4aa; 今天&#xff0c;就让我带你一起揭秘&#xff0c;那些能够助力亨…

机器学习/数据分析案例---糖尿病预测

&#x1f368; 本文为&#x1f517;365天深度学习训练营 中的学习记录博客&#x1f356; 原作者&#xff1a;K同学啊 前言 这是一篇数据分析/机器学习很好的入门案例&#xff0c;对糖尿病的影响进行预测和分析通过随机森林预测&#xff0c;平均准确率和召回率都不错不足&#x…

Photomator 3.3.22 (macOS Universal) - 照片编辑软件

Photomator 3.3.22 (macOS Universal) - 照片编辑软件 适用于 Mac、iPhone 和 iPad 的终极照片编辑器 请访问原文链接&#xff1a;https://sysin.org/blog/photomator/&#xff0c;查看最新版。原创作品&#xff0c;转载请保留出处。 作者主页&#xff1a;sysin.org Photoma…

美发店拓客营销预约到店连锁小程序拓展

传统印象里的10元美发店&#xff0c;在城市里已然升级为大店&#xff0c;服务多样化&#xff0c;价格也是几十元到几千元不等数个区间&#xff0c;除了单店外也有连锁品牌进行区域拓展&#xff0c;以量和品牌形象收获更多客户和自身的宣传等。 尤其是规模相对较大的门店&#…

AcWing 896. 最长上升子序列 II

学习视频↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓ 【E04 线性DP 最长上升子序列 二分优化】 O ( n l o g n ) O(nlogn) O(nlogn) #include<iostream> #include<algorithm> #define N 100010 using namespace std; int n; int a[N],q[N]; i…

【软件工程】软件工程

考点2 软件工程 一、定义 二、软件工程基本原理 三、软件工程方法学&#xff08;范型&#xff09; 题目 选择题

数字乡村振兴智慧农业整体规划建设方案

1. 项目建设需求 《数字乡村振兴智慧农业整体规划建设方案》旨在通过遥感、物联网等技术&#xff0c;实现土地资源监测、测土配方施肥、农产品销售分析、农资监管、物流配送监管、农业专家库、市场分析、产业链应用和金融服务。 2. 项目需求分析 项目需求覆盖生产、经营、监…

关于计算机网络原理问题

2017年12月07日星期四&#xff0c; 问题&#xff1a; 答案&#xff1a; 接下来&#xff0c;我们来分析和解答&#xff0c; 首先&#xff0c;你要知道&#xff0c;一个byte&#xff08;字节&#xff09;能表示两个十六进制数&#xff0c;那么四个字节就可以表示8个十六进制数…

Simulink代码生成:关系运算与逻辑运算

文章目录 1 引言2 模块使用实例2.1 关系运算2.2 关系运算 3 代码生成4 总结 1 引言 在Simulink中经常需要判断两个信号的大小关系、是否相等&#xff0c;或者判断布尔类型信号的与、或、非等。本文研究通过关系运算与逻辑运算模块实现上述需求。 2 模块使用实例 2.1 关系运算…

hello树先生——二叉搜索树

文章目录 一.搜索二叉树的性质二&#xff0c;功能函数接口1.二叉树的节点结构&#xff0c;分为左右指针和数据2.二叉树的插入函数3.删除接口4.中序遍历 三.测试项目 一.搜索二叉树的性质 若它的左子树不为空&#xff0c;则左子树上所有节点的值都小于根节点的值若它的右子树不…

uniapp scroll-view滚动触底加载 height高度自适应

背景&#xff1a; scroll-view组件是使用&#xff0c;官网说必须给一个高度height&#xff0c;否则无法滚动&#xff0c;所以刚开始设置了<scroll-view :style"height: 94vh" :scroll-y"true">设置了一个高度&#xff0c;想着vh应该挺合适的&#xf…

眼镜清洗机哪个品牌好?2024超声波清洗机推荐

眼镜作为日常生活不可或缺的配件&#xff0c;其卫生状况直接影响着我们的健康。日常简单的擦拭往往忽略了隐匿于镜片细微处的细菌群落&#xff0c;未彻底清洁的眼镜可能潜藏健康隐患。因此&#xff0c;深度清洁眼镜显得尤为关键&#xff0c;而超声波清洗机正是一种高效便捷的解…

探索《黑神话:悟空》背后的先进技术

黑神话&#xff1a;悟空》是一款备受期待的国产动作角色扮演游戏&#xff0c;凭借其令人惊叹的画面效果和极具深度的游戏玩法&#xff0c;吸引了全球玩家的目光。究竟是什么让这款游戏如此出色&#xff1f;让我们一起来探讨《黑神话&#xff1a;悟空》在开发过程中采用的几项尖…

java计算机毕设课设—固定资产管理系统(附源码、文章、相关截图、部署视频)

这是什么系统&#xff1f; java计算机毕设课设—固定资产管理系统(附源码、文章、相关截图、部署视频) 获取资料方式在最下方 本系统主要用于高校中的“资产”进行管理。具体地讲&#xff0c;固定资产管理系统就是通过资产的增加、删除、查看、借出、归还、维修等一系列手段…

lvs-nat的https模式设置

前言&#xff1a;LVS工作模式分为NAT模式、TUN模式、以及DR模式。在lvs服务器上&#xff0c;设置虚拟ip并做负载均衡使用。使用LVS架设的服务器集群系统有三个部分组成&#xff1a;最前端的负载均衡层&#xff08;Loader Balancer&#xff09;&#xff0c;中间的服务器群组层&a…