Xuggle和java库路径

我正在用Java编写截屏video应用程序。 我决定使用Xuggle来做这件事,然后我跟着xuggle wiki上的安装说明。

我使用%XUGGLE_HOME%\ bin和%XUGGLE_HOME%\ lib设置了PATH环境。 一切似乎都好。 我把这个应用程序作为RCP插件。 我在“RCP-mail”模板上试了一下,插件正常工作,video生成正确。

但是,当我决定在“真正的”应用程序上使用它时,插件崩溃了一个奇怪的错误消息:

开始捕获

2011-11-10 08:08:45,438 [Thread-5] WARN com.xuggle.ferry.JNILibraryLoader – 失败:库的库加载:xuggle-xuggler; version:3:绝对路径:C:\ Program Files(x86)\ Xuggle \ bin \ libxuggle-xuggler-3.dll; 错误:java.lang.UnsatisfiedLinkError:C:\ Program Files(x86)\ Xuggle \ bin \ libxuggle-xuggler-3.dll:找不到依赖库

2011-11-10 08:08:45,447 [Thread-5] WARN com.xuggle.ferry.JNILibraryLoader – 失败:库的库加载:xuggle-xuggler; version:3:绝对路径:C:\ Program Files(x86)\ Xuggle \ bin \ libxuggle-xuggler-3.dll; 错误:java.lang.UnsatisfiedLinkError:C:\ Program Files(x86)\ Xuggle \ bin \ libxuggle-xuggler-3.dll:找不到依赖库

2011-11-10 08:08:45,453 [Thread-5] ERROR com.xuggle.ferry.JNILibraryLoader – 无法加载库:xuggle-xuggler; 版本:3; 请访问http://www.xuggle.com/xuggler/faq/以查找此问题的常见解决方案

但这很奇怪,因为java.library.path定义得很好:

logger.info(System.getProperty("java.library.path")); 

回报

 Nov 10, 2011 8:08:45 AM com.gvs.tools.ui.record.video.handler.RecordHandler startRecording INFO: C:\Program Files (x86)\Java\jre6\bin;C:\Windows\Sun\Java\bin;C:\Windows\system32;C:\Windows;C:/Program Files (x86)/Java/jre6/bin/client;C:/Program Files (x86)/Java/jre6/bin;C:/Program Files (x86)/Java/jre6/lib/i386;C:\Program Files (x86)\Xuggle\bin;C:\Program Files (x86)\Xuggle\lib;C:\Program Files (x86)\NVIDIA Corporation\PhysX\Common;C:\Windows\system32;C:\Windows;C:\Windows\System32\Wbem;C:\Windows\System32\WindowsPowerShell\v1.0\;C:\Program Files (x86)\JProbe 8.3\bin;C:\Program Files\TortoiseSVN\bin;D:\Work\Paul\eclipse;;. 

我缺少使插件与此应用程序一起工作? 此问题是由于应用程序使用其他本机库(如3D-dll)的事实吗?

以下是用于制作截屏video的代码:

 RecordHandler.java: private void startRecording() { Logger logger = Logger.getLogger(RecordHandler.class.getName()); logger.info(System.getProperty("java.library.path")); // Initialize framesQueue framesQueue = new LinkedBlockingQueue(); // Initialize the capture thread captureThread = new ScreenCapturer(); captureThread.setCaptureFramesQueue(framesQueue); // Initialize the recorder encoderThread = new FrameEncoder("test.mp4"); encoderThread.setCapturedFramesQueue(framesQueue); // Start capture captureThread.start(); // wait for the Queue to be feed before encoding try { Thread.sleep(1000L); } catch (InterruptedException e) { } encoderThread.start(); } 

ScreenCapturer.java:

  @Override public void run() { // Retrieve the application main window's shell Display.getDefault().asyncExec(new Runnable() { @Override public void run() { appShell = Display.getCurrent().getActiveShell(); } }); isRunning = true; System.out.println("Starting Capture"); for (numberOfFramesTaken = 0; isRunning && numberOfFramesTaken <= IVideoEncoderConfiguration.MAXIMUM_NUMBER_OF_FRAMES; numberOfFramesTaken++) { try { takeScreenShot(); Thread.sleep(IVideoEncoderConfiguration.CAPTURE_TIME_INTERVAL_MILLIS); } catch (InterruptedException e) { } } System.out.println("Capture has ended"); System.out.println("Number of frames taken: " + numberOfFramesTaken); } /** * Take a screen capture and store it in the capturedFramesQueue */ private void takeScreenShot() { Display.getDefault().asyncExec(new Runnable() { @Override public void run() { if (appShell != null) { Rectangle bounds = appShell.getBounds(); java.awt.Rectangle awtBounds = new java.awt.Rectangle(bounds.x, bounds.y, bounds.width, bounds.height); final BufferedImage screenCapture = robot.createScreenCapture(awtBounds); try { capturedFramesQueue.put(screenCapture); } catch (InterruptedException e) { } } } }); } 

FrameEncoder.java:

 public void run() { isRunning = true; String outFile = outputdirectoryPath + outputFileName; // First, let's make a IMediaWriter to write the file. final IMediaWriter writer = ToolFactory.makeWriter(outFile); // Retrieve the first frame to guess video dimensions BufferedImage firstFrame = null; try { firstFrame = capturedFramesQueue.take(); } catch (InterruptedException e) { } if (firstFrame == null) { return; } // We tell it we're going to add one video stream, with id 0, // at position 0, and that it will have a fixed frame rate of // FRAME_RATE. writer.addVideoStream(0, 0, IVideoEncoderConfiguration.FRAME_RATE, firstFrame.getWidth(), firstFrame.getHeight()); long startTime = System.nanoTime(); for (numberOfFramesRecorded = 0; isRunning && numberOfFramesRecorded <= IVideoEncoderConfiguration.MAXIMUM_NUMBER_OF_FRAMES; numberOfFramesRecorded++) { // Retrieve the captured frame try { final BufferedImage currentFrame = convertToType(capturedFramesQueue.take(), BufferedImage.TYPE_3BYTE_BGR); // encode the next frame writer.encodeVideo(0, currentFrame, System.nanoTime() - startTime, TimeUnit.NANOSECONDS); // sleep, time depending of FRAME_RATE Thread.sleep(IVideoEncoderConfiguration.CAPTURE_TIME_INTERVAL_MILLIS); } catch (InterruptedException e) { } } // Get the remaining frame on the queue Collection frames = new LinkedList(); capturedFramesQueue.drainTo(frames, IVideoEncoderConfiguration.MAXIMUM_NUMBER_OF_FRAMES - numberOfFramesRecorded); for (BufferedImage frame : frames) { BufferedImage currentFrame = convertToType(frame, BufferedImage.TYPE_3BYTE_BGR); writer.encodeVideo(0, currentFrame, System.nanoTime() - startTime, TimeUnit.NANOSECONDS); } // close the MediaWriter, write the trailer if needed writer.close(); } 

我知道这有点晚了,但问题是Xuggler要求所有的DLL都在操作系统的加载路径环境中,而不仅仅是java.library.path

这意味着使用Xuggle安装的所有DLL(例如,libavcodec.dll)都需要位于启动Java的进程的%PATH%环境变量中。

原因可能是依赖项jar或版本冲突不可用。

在类路径中添加以下jar对我来说很好:

xuggle-xuggler-5.4.jar slf4j-api-1.6.4.jar logback-core-1.0.0.jar logback-classic-1.0.0.jar