我正在进行的一个视频 session 项目使用JMF捕获视频和音频,并将其传输到另一个端点。问题是我的团队不希望产品的用户必须安装JMF。

我认为可能值得分享我们对这个问题的解决方案。有用。效果很好。我对您的问题是:有人有更好的方法吗?

环境:Windows,XP及更高版本

  • 下载Windows的JMF
  • 在您的计算机上安装
  • 安装jmf之后,在system32文件夹中找到以下dll:

    jmacm.dll
    jmam.dll
    jmcvid.dll
    jmdaud.dll
    jmdaudc.dll
    jmddraw.dll
    jmfjawt.dll
    jmg723.dll
    jmgdi.dll
    jmgsm.dll
    jmh261.dll
    jmh263enc.dll
    jmjpeg.dll
    jmmci.dll
    jmmpa.dll
    jmmpegv.dll
    jmutil.dll
    jmvcm.dll
    jmvfw.dll
    jmvh263.dll
    jsound.dll
  • dll复制到一个临时文件夹
  • 找到jmf.properties文件(在您的计算机上进行搜索)
  • 下载JMF源代码
    在源代码中,找到以下文件:

  • JMFinit.java
    JMRPropertiesGen.java
    Registry.java
    RegistryGen.java
  • 创建一个包;我称它为JMFNoInstall
  • 添加第6步中列出的文件
  • 将此包添加一个名为Main的类,如下所示:

  • package JMFNoInstall;
    // add your imports and whatnot here
    public class Main()
    {
        public Main()
        {
            JMFinit.main(null);
            JMFPropertiesGen.main(null);
            Registry.main(null);
            RegistryGen.main(new String[] {
                new File(".").getAbsolutePath(),
                "registrylib"
            });
        }
    }
    
    jmf.properties文件需要与具有main方法的类位于同一文件夹中,或者与包含main方法的JAR存档位于同一文件夹中。dll需要进入win32文件夹。您可以让程序检查它们是否在win32文件夹中。如果不是,您可以让它从某个位置复制它们。每当上面列出的jmf.properties类运行时,Main文件都会更新。您只需要运行一次,第一次运行该程序,或者用户想添加新的捕获设备。最后,只需确保Windows JMF下载随附的jmf.jar文件和jmfcom.jar包含在类路径中。此时,您很好。 JMF的所有功能,而无需实际安装。

    确实没有很多工作要做,您可以很轻松地将其合并到自定义安装程序中。

    有人找到了更好的方法吗?这样做有一些陷阱。

    编辑:我认为分享一些我创建的代码可能是值得的。当然,您需要对其进行修改以处理您的问题。它可能不会编译,但是缺少的内容应该足够容易地重新创建。但是认为这可能是帮助人们的良好起点。 detectCaptureDevices函数可能会对大多数人有所帮助。我现在去更新这个类。
    import GUI.Window;import GlobalUtilities.OS;import GlobalUtilities.ProgressBar;import GlobalUtilities.FileUtilities;import java.io.File;import java.util.ArrayList;import java.util.Vector;import javax.swing.text.Utilities;/** * This class providex easy access to the most needed info about JMF. You can test * a JMF install (Windows only currently) and also get info about the captrue * devices hooked up to JMF. * @author dvargo */public class JMFRunner{ /** * Show the status of operations */ final ProgressBar theBar = new ProgressBar(); /** * Location where the dll's JMF relies on need to be placed */ final String windowsDllFolder = "C:\\WINDOWS\\system32\\"; final String linuxDllFolder = "/usr/lib/"; /** * Dll's that JMF uses */ final String[] windowsDllList = new String[]{ "jmacm.dll", "jmam.dll", "jmcvid.dll", "jmdaud.dll", "jmdaudc.dll", "jmddraw.dll", "jmfjawt.dll", "jmg723.dll", "jmgdi.dll", "jmgsm.dll", "jmh261.dll", "jmh263enc.dll", "jmjpeg.dll", "jmmci.dll", "jmmpa.dll", "jmmpegv.dll", "jmutil.dll", "jmvcm.dll", "jmvfw.dll", "jmvh263.dll", "jsound.dll"}; String[] linuxDllList = new String[]{ "libjmcvid.so", "libjmdaud.so", "libjmfjawt.so", "libjmg723.so", "libjmgsm.so", "libjmh261.so", "libjmh263enc.so", "libjmjpeg.so", "libjmmpa.so", "libjmmpegv.so", "libjmmpx.so", "libjmutil.so", "libjmv4l.so", "libjmxlib.so" }; String [] dlls= null; String dir = null; /** * List of the video capture devices found by JMF */ Vector videoDevices = null; /** * List of the audio capture devices found by JMF */ Vector audioDevices = null; public JMFRunner() { if(OS.isWindows()) { dlls = windowsDllList; dir = windowsDllFolder; } else if(OS.isLinux()) { dlls = linuxDllList; dir = linuxDllFolder; } else { Window.getLogger().severe("Operating system does not support JMF"); } } /** * Adds new capture devices */ public void detectCaptureDecives() { Thread theTread = new Thread(theBar); theTread.start(); theBar.repaint(); JMFInit.main(new String[] {""}); JMFPropertiesGen.main(new String[] {""}); Registry.main(new String[] {""}); RegistryGen.main(new String[] {"-d", new File(".").getAbsolutePath(), "registrylib" }); theBar.setMessage(""); theBar.stop(); } /** * Verifies that all the dll's that JMF needs are in their correct spot * @return True if all dlls are in their correct spot, false otherwise */ public boolean detectDlls() { boolean retVal = true; String currFile; for(String currDll : dlls) { currFile = dir + currDll; if(! new File(currFile).exists()) { Window.getLogger().severe("Can not find dll " + currFile + " for JMF"); retVal = false; } } return retVal; } //Doesnt work quite yet public boolean installLibraryFiles() { boolean retVal = true; String currFile; for(String currDll : dlls) { currFile = dir + currDll; File newDll = new File(currFile); //see if this dll is already there if(!newDll.exists()) { //its not there so lets copy it try { FileUtilities.copy(newDll,FileUtilities.getResourceFile("/JMFManager/Resources/"+currDll,currDll)); } catch(Exception e) { retVal = false; } } } return retVal; } /** * Returns the location of the jmf.properties file that STix is using * @return THe locaiton of the JMF properties */ public String getJMFPropertiesFileLocation() { return Registry.getJMFPropertiesFileLocation(); } /** * Returns a list of the audio devices found by JMF * @return Returns an Arraylist containing info about the audio capture devices */ public ArrayList getAudioDevices() { DeviceFinder df = new DeviceFinder(); audioDevices = df.getSoundCaptureDevices(); return new ArrayList(audioDevices); } /** * Returns a list of the video decives deteced by JMF * @return returns an arraylist with info of the video capture devices */ public ArrayList getVideoDevices() { DeviceFinder df = new DeviceFinder(); videoDevices = df.getVideoCaptureDevices(); return new ArrayList(videoDevices); } public static void main(String [] args) { JMFRunner x = new JMFRunner(); //x.detectCaptureDecives(); x.installLibraryFiles(); System.out.println(x.detectDlls()); System.out.println(x.getJMFPropertiesFileLocation()); System.out.println(x.getAudioDevices()); System.out.println(x.getVideoDevices()); }}
    DeviceFinder.java
    import java.util.Vector;import javax.media.*;import javax.media.format.*;/** * this class gets information about capture devices (mics and cameras) */public class DeviceFinder { Vector videoDevices = new Vector(); Vector audioDevices = new Vector(); /** * Constructor * Creates a new DeviceFinder */ public DeviceFinder() { /*retrieve ALL video and audio devices*/ videoDevices = CaptureDeviceManager.getDeviceList(new VideoFormat(null)); audioDevices = CaptureDeviceManager.getDeviceList(new AudioFormat(null)); } /** * purpose: Get information on all Video capture devices on the system * @return java.util.Vector
    a vector of attributes */ public Vector getVideoCaptureDevices() { return videoDevices; } /** * purpose: Get information on all audio capture devices on the system * @return java.util.Vector
    a vector of attributes */ public Vector getSoundCaptureDevices() { return audioDevices; } /** * retrieve the first video capture device */ public CaptureDeviceInfo getPrimaryVideoCaptureDevice() { return (CaptureDeviceInfo)videoDevices.get(0); } /*retrieve the first audio capture device*/ public CaptureDeviceInfo getPrimaryAudioCaptureDevice() { return (CaptureDeviceInfo)audioDevices.get(0); } /** * get the first video device name * @return String
    the name of the video device */ public String getVideoCaptureDeviceName() { return ((CaptureDeviceInfo)videoDevices.get(0)).getName(); } /** * get the first audio device name * @return String
    the name of the audio device */ public String getAudioCaptureDeviceName() { return ((CaptureDeviceInfo)audioDevices.get(0)).getName(); } /** * get the first video device media locator * @return MediaLocator */ public MediaLocator getVideoMediaLocator() { return ((CaptureDeviceInfo)videoDevices.get(0)).getLocator(); } /** * get the first audio device media locator * @return MediaLocator */ public MediaLocator getAudioMediaLocator() { return ((CaptureDeviceInfo)audioDevices.get(0)).getLocator(); } /** * get the video device media locator at index idx * @param idx index of the media locator (0 is the first/default, * as ordered by *
    the JMFRegistry) * @return MediaLocator */ public MediaLocator getVideoMediaLocator(int idx) { if(idx >= videoDevices.size()) { return null; } return ((CaptureDeviceInfo)videoDevices.get(idx)).getLocator(); } /** * get the audio device media locator at index idx * @param idx index of the audio device (as ordered by the JMFRegistry) * @return MediaLocator */ public MediaLocator getAudioMediaLocator(int idx) { return ((CaptureDeviceInfo)audioDevices.get(idx)).getLocator(); } /** * * @param args */ public static void main(String[] args) { DeviceFinder df = new DeviceFinder(); //DEBUG: System.out.println(df.getVideoMediaLocator()); System.out.println(df.getAudioMediaLocator()); }}

    最佳答案

    我认为没有更好的方法。除非这些DLL是通过路径名显式加载的,否则您只需要确保它们在系统路径中即可,因此,如果这些DLL生活在JVM可执行文件的旁边,那么它也应该起作用。 Windows确实在系统路径中隐式包含了程序从其启动的目录,因此这是另一个可能的位置。

    安装程序是一把双刃剑,它们使添加新功能和稍后删除它变得容易,但也使部署使用该产品的解决方案变得更加困难。

    通常,关于Java的一件好事是,您无需安装它即可正常工作。本质上,一旦在一个系统上执行了JRE的安装,就可以将其 bundle 并以zip文件的形式在另一个系统上使用。 Java不需要显式注册DLL,因为它会根据需要动态加载它们。

    10-07 19:28
    查看更多