当前位置: 首页 > 知识库问答 >
问题:

JavaFX MediaPlayer无法播放本地m3u8文件

虞博涛
2023-03-14

我想使用MediaPlayer/MediaView在我的JavaFX应用程序中显示web cam的实时流。我尝试使用ffmpeg录制HLS并播放生成的m3u8文件,但这会引发以下异常(VLC播放视频时没有问题):

MediaException: UNKNOWN : com.sun.media.jfxmedia.MediaException: Could not create player! : com.sun.media.jfxmedia.MediaException: Could not create player!
    at javafx.scene.media.MediaException.exceptionToMediaException(MediaException.java:146)
    at javafx.scene.media.MediaPlayer.init(MediaPlayer.java:511)
    at javafx.scene.media.MediaPlayer.<init>(MediaPlayer.java:414)
    at de.fraunhofer.iosb.ias.flow.assessment.management.monitor.MonitorViewController.testStream(MonitorViewController.java:203)
    ... 58 more
Caused by: com.sun.media.jfxmedia.MediaException: Could not create player!
    at com.sun.media.jfxmediaimpl.NativeMediaManager.getPlayer(NativeMediaManager.java:274)
    at com.sun.media.jfxmedia.MediaManager.getPlayer(MediaManager.java:118)
    at javafx.scene.media.MediaPlayer.init(MediaPlayer.java:467)
    ... 60 more

我调试了播放器的创建,当GSTMediaPlayer时,错误发生在GSTMediaPlayer的构造函数中。调用gstInitPlayer()。此本机方法返回错误代码257,javafx将其映射到MediaError。错误\媒体\空值

我使用以下ffmpeg命令录制视频:

ffmpeg -hide_banner -y -rtbufsize 250MB -f dshow -pixel_format yuv420p -video_size 960x720 -i video="Logitech HD Pro Webcam C920" -c:v libx264 -crf 20 -pix_fmt yuv420p out.m3u8

我非常确定编码符合javafx的要求,因为如果我将输出容器从m3u8更改为mp4,使用完全相同的ffmpeg命令播放视频是没有问题的。

这是m3u8文件的ffprobe输出:

Input #0, hls,applehttp, from 'out.m3u8':
  Duration: 00:00:24.23, start: 1.466667, bitrate: 0 kb/s
  Program 0
    Metadata:
      variant_bitrate : 0
    Stream #0:0: Video: h264 (High) ([27][0][0][0] / 0x001B), yuv420p, 960x720, 30 fps, 30 tbr, 90k tbn, 60 tbc

对于mp4文件:

Input #0, mov,mp4,m4a,3gp,3g2,mj2, from 'out.mp4':
  Metadata:
    major_brand     : isom
    minor_version   : 512
    compatible_brands: isomiso2avc1mp41
    encoder         : Lavf57.41.100
  Duration: 00:01:04.93, start: 0.000000, bitrate: 1676 kb/s
    Stream #0:0(und): Video: h264 (High) (avc1 / 0x31637661), yuv420p, 960x720, 1673 kb/s, 30 fps, 30 tbr, 10000k tbn, 60 tbc (default)
    Metadata:
      handler_name    : VideoHandler

生成的m3u8文件如下所示:

#EXTM3U
#EXT-X-VERSION:3
#EXT-X-TARGETDURATION:9
#EXT-X-MEDIA-SEQUENCE:0
#EXTINF:8.333322,
out0.ts
#EXTINF:8.333333,
out1.ts
#EXTINF:7.133322,
out2.ts
#EXTINF:0.433333,
out3.ts
#EXT-X-ENDLIST

更新:在我找到这个参考m3u文件后,我认为问题是该文件存储在本地,而不是通过HTTP传递。视频播放这个很好:

Media media = new Media("http://download.oracle.com/otndocs/products/javafx/JavaRap/prog_index.m3u8");
MediaPlayer player = new MediaPlayer(media);
player.setAutoPlay(true);
mediaView.setMediaPlayer(player);

但是在我下载了参考m3u及其所有片段并试图像这样打开本地文件后,错误再次发生:

File video = new File("H://Projects//Tools//ref//prog_index.m3u8");
Media media = new Media(video.toURI().toString());
MediaPlayer player = new MediaPlayer(media);
player.setAutoPlay(true);
mediaView.setMediaPlayer(player);

我试图改变我的m3u文件,以便分段引用绝对路径。我尝试了不同的符号(H:\f\out0.tsH:/f/out0.tsH://f//out0.tsfile:/H:/f/out0.tsfile:///H:/f/out0.ts),但我无法让它工作。

共有2个答案

姬博瀚
2023-03-14

问题在于WebEngine访问本地文件系统[文件://]。这就是它是如何发生的。

//Started app [run-able .jar] and loaded a start page [resource in .jar] 
protected static String Some_Resource_in_a_JAR = "/jimmylandstudios/gui/index.html";
webEngine.load(getClass()
.getResource(" + Some_Resource_in_a_JAR + ")
.toExternalForm());
//So, you can forget using the file:// protocol now. 

我的答案是:对任何创建/修改的文件使用HTTP:服务器。或者更好,

//Avoid issue [accessing local files] 
protected static String Extracted_Resource_from_JAR = "/jimmylandstudios/gui/index.html";
webEngine.load("file://" + Extracted_Resource_from_JAR + ");

简单地说:如果您正在访问本地文件,请使用file://协议启动WebEngine。

云骏奇
2023-03-14

不幸的是,看来你在这里运气不好。这是JDK内部的相关逻辑位:

com中。太阳媒体jfxmedia。定位器。定位器

public ConnectionHolder createConnectionHolder() throws IOException {
    // [...] cache lookup elided
    ConnectionHolder holder;
    if ("file".equals(scheme)) {
        holder = ConnectionHolder.createFileConnectionHolder(uri);
    } else if (uri.toString().endsWith(".m3u8") || uri.toString().endsWith(".m3u")) {
        holder = ConnectionHolder.createHLSConnectionHolder(uri);
    }

如您所见,第一个检查是针对文件方案,此时您会被不客气地发送到处理实际媒体文件的逻辑。HLS播放列表处理由稍后检查文件扩展名触发。m3u8但到那时已经太晚了,您的本地文件已匹配先前的条件并发送到错误的位置。你可以辩称这是一个bug并将其归档,尽管这有点像边缘案例。

 类似资料:
  • 我正在尝试使用android mediaplayer类播放存储在SD卡中的本地m3u8文件。m3u8文件和。ts文件位于同一目录中。第三方播放器(如MXPlayer)加入ts文件,并在我从中打开m3u8时播放视频。但是使用android mediaplayer类会引发以下错误` 无法创建媒体播放器错误:setDataSourceFD失败:状态=0x8000000 java。木卫一。IOExcept

  • 我试图让媒体播放器播放存储在本地/外部存储器中的媒体文件。 媒体文件使用单独的活动下载并存储在本地/外部存储中。有关存储的示例代码,请参阅下面。 对于播放同一文件,我使用。 但是,媒体播放器拒绝播放文件,并且总是以错误(1,)失败。我真的是无能为力,使这个媒体播放器运行,因为我似乎已经做了一切与代码示例内联,使它从本地/外部存储读取文件。 注意:当我替换一个本地文件与一个文件从res/生文件夹,这

  • 我正在尝试使用HTTP直播(HLS)将视频流传输到我的电脑和iPhone。在阅读了苹果的“HTTP直播概述”以及“为iPhone和iPad创建和部署HTTP直播媒体的最佳实践”之后,我有点卡住了。 我获取了我的源文件(一个mkv),并使用ffmpeg对文件进行编码,采用MPEG-TS格式、苹果推荐的设置和基准3.0配置文件: 不用担心。我使用预编译的分段工具来分割视频并构建一个. m3u8播放列表

  • 我遵循了本教程:http://what-when-how.com/javafx-2/playing-audio-using-the-media-classes-javafx-2-part-1/ 我有相应的资源文件夹在相应的目录中。类文件,但我仍然不能播放音频。mp3文件与教程中的不同,但我也有一个. wav等效文件,发现JavaFX可以开箱播放*. wav文件,但不能播放mp3文件。怎么回事啊?

  • 基于StackExchange的代码,我编写了打开wav文件的代码。wav文件本身是一个有效的文件,因为它可以与我的Python程序正常配合使用。但是javascript函数不起作用。声音文件与我的html文件位于同一文件夹中。 任何帮助都将不胜感激。

  • 标记为“good”的文件可以正确播放,而标记为“bad”的文件则不能。两个文件在同一个目录中;两个文件都使用音乐播放器播放;并且这两个文件都可以在Windows7机器上使用Python3.4和pygame。