Of course! Using MediaInfo in Java is a common requirement for getting detailed metadata from audio and video files. The most reliable way to do this is by using the MediaInfo library itself and interacting with it via a Java process.
Here’s a comprehensive guide covering the concepts, different approaches, and a complete, runnable Java example.
Understanding the Core Concept
The standard MediaInfo library is written in C++. It doesn't have a native Java API. Therefore, the standard approach is to use Java's ProcessBuilder to launch the MediaInfo command-line executable (.exe on Windows, MediaInfo on Linux/macOS) and capture its output.
The command looks like this:
MediaInfo.exe --Output="XML" "C:\path\to\your\movie.mp4"
This command will print the file's metadata in a structured XML format, which is very easy for Java to parse.
Approaches to Use MediaInfo in Java
| Approach | Pros | Cons | Best For |
|---|---|---|---|
| Command-Line Execution | - Official & Reliable: Uses the official library. - Complete & Accurate: Gets all metadata the library supports. - Platform Independent: Works on Windows, Linux, macOS. |
- Performance Overhead: Spawning a new process for each file can be slow. - External Dependency: Requires the MediaInfo executable to be present on the system. |
Most use cases. It's the standard, most robust method. |
| JNI (Java Native Interface) | - High Performance: Direct C++ call, no process spawning. - Clean API: Can create a nice Java wrapper. |
- Very Complex: Requires writing C/C++ glue code. - Platform-Specific Binaries: Need to compile/link a .dll (Windows) or .so (Linux) file.- Maintenance Burden: JNI code is notoriously difficult to debug and maintain. |
High-performance applications where process overhead is a critical bottleneck. |
| Third-Party Java Wrappers | - Easy to Use: Provides a direct Java API. -- No need to handle processes manually. |
- May Not Be Updated: Often lag behind the official MediaInfo library. - Potential for Bugs: Quality depends on the maintainer. |
Quick prototyping or if you want to avoid the command-line complexity. |
Recommendation: For 99% of projects, Approach 1 (Command-Line Execution) is the best choice. It's stable, accurate, and relatively simple to implement.
Step-by-Step Guide: Command-Line Execution (Recommended)
This is the most practical and widely used method.
Step 1: Get the MediaInfo Executable
- Go to the official MediaInfo download page: https://mediaarea.net/en/MediaInfo/Download
- Download the package for your operating system. For development, the Command Line Interface (CLI) version is sufficient.
- Extract the downloaded archive. You will find an executable file like
MediaInfo.exe(Windows) orMediaInfo(Linux/macOS). - Place the executable somewhere accessible by your Java application. A common practice is to place it in a dedicated folder within your project (e.g.,
lib/media_info/).
Step 2: Write the Java Code
We will create a Java class that takes a file path, runs the MediaInfo command, captures the XML output, and parses it into a Java object.
Project Structure:
MyProject/
├── src/
│ └── com/
│ └── example/
│ └── mediainfo/
│ └── MediaInfoParser.java
├── lib/
│ └── media_info/
│ ├── MediaInfo.exe (Windows)
│ └── MediaInfo (Linux/macOS)
└── pom.xml (If using Maven)
pom.xml (Maven): It's good practice to depend on a library for XML parsing. javax.xml.bind is a standard choice.
<project xmlns="http://maven.apache.org/POM/4.0.0"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<groupId>com.example</groupId>
<artifactId>mediainfo-java-demo</artifactId>
<version>1.0-SNAPSHOT</version>
<properties>
<maven.compiler.source>11</maven.compiler.source>
<maven.compiler.target>11</maven.compiler.target>
</properties>
<dependencies>
<!-- For XML parsing (JAXB is part of Java SE 8, but may need this for newer Java versions) -->
<dependency>
<groupId>javax.xml.bind</groupId>
<artifactId>jaxb-api</artifactId>
<version>2.3.1</version>
</dependency>
<dependency>
<groupId>org.glassfish.jaxb</groupId>
<artifactId>jaxb-runtime</artifactId>
<version>2.3.1</version>
</dependency>
</dependencies>
</project>
MediaInfoParser.java:
This class handles the process execution and XML unmarshalling.
package com.example.mediainfo;
import javax.xml.bind.JAXBContext;
import javax.xml.bind.JAXBException;
import javax.xml.bind.Unmarshaller;
import java.io.File;
import java.io.IOException;
import java.util.ArrayList;
import java.util.List;
public class MediaInfoParser {
// Path to the MediaInfo executable.
// IMPORTANT: Adjust this path to where you placed the executable.
private static final String MEDIA_INFO_PATH = "lib/media_info/MediaInfo.exe";
/**
* Parses a media file and returns its metadata.
*
* @param file The media file to analyze.
* @return A MediaInfo object containing the metadata.
* @throws IOException If the MediaInfo executable cannot be found or run.
* @throws InterruptedException If the process is interrupted.
* @throws JAXBException If the XML output cannot be parsed.
*/
public MediaInfo getMediaInfo(File file) throws IOException, InterruptedException, JAXBException {
if (!file.exists()) {
throw new IllegalArgumentException("File not found: " + file.getAbsolutePath());
}
// Build the command
ProcessBuilder pb = new ProcessBuilder(
MEDIA_INFO_PATH,
"--Output=XML",
file.getAbsolutePath()
);
// Start the process
Process process = pb.start();
// Wait for the process to finish
int exitCode = process.waitFor();
if (exitCode != 0) {
throw new IOException("MediaInfo process exited with error code: " + exitCode);
}
// Parse the XML output
JAXBContext jaxbContext = JAXBContext.newInstance(MediaInfo.class);
Unmarshaller jaxbUnmarshaller = jaxbContext.createUnmarshaller();
// MediaInfo returns a root element <MediaInfo> which contains a list of <track> elements.
// The JAXB class is structured to match this.
return (MediaInfo) jaxbUnmarshaller.unmarshal(process.getInputStream());
}
/**
* Main method for demonstration.
*/
public static void main(String[] args) {
// Create a dummy video file for testing.
// Replace this with the path to your own media file.
File mediaFile = new File("C:/path/to/your/video.mp4");
MediaInfoParser parser = new MediaInfoParser();
try {
System.out.println("Analyzing file: " + mediaFile.getName());
MediaInfo info = parser.getMediaInfo(mediaFile);
// Print general information (track of type General)
if (info.getTrack() != null && !info.getTrack().isEmpty()) {
Track generalTrack = info.getTrack().get(0);
System.out.println("\n--- General Information ---");
System.out.println("Format: " + generalTrack.getFormat());
System.out.println("Duration: " + generalTrack.getDuration());
System.out.println("Overall Bit Rate: " + generalTrack.getOverallBitRate());
}
// Print video information (track of type Video)
if (info.getTrack().stream().anyMatch(t -> "Video".equals(t.getType()))) {
Track videoTrack = info.getTrack().stream()
.filter(t -> "Video".equals(t.getType()))
.findFirst()
.get();
System.out.println("\n--- Video Information ---");
System.out.println("Codec: " + videoTrack.getCodec());
System.out.println("Width: " + videoTrack.getWidth());
System.out.println("Height: " + videoTrack.getHeight());
System.out.println("Frame Rate: " + videoTrack.getFrameRate());
System.out.println("Bit Depth: " + videoTrack.getBitDepth());
}
// Print audio information (track of type Audio)
if (info.getTrack().stream().anyMatch(t -> "Audio".equals(t.getType()))) {
Track audioTrack = info.getTrack().stream()
.filter(t -> "Audio".equals(t.getType()))
.findFirst()
.get();
System.out.println("\n--- Audio Information ---");
System.out.println("Codec: " + audioTrack.getCodec());
System.out.println("Channels: " + audioTrack.getChannels());
System.out.println("Sample Rate: " + audioTrack.getSamplingRate());
System.out.println("Bit Rate: " + audioTrack.getBitRate());
}
} catch (Exception e) {
e.printStackTrace();
}
}
}
Step 3: Create JAXB Classes (for XML Parsing)
The MediaInfo executable outputs XML. We need Java classes that mirror this XML structure. You can generate these classes from an XSD schema, but for this common format, we can write them manually.
Create these three classes in the same package (com.example.mediainfo):
MediaInfo.java (Root Element)
package com.example.mediainfo;
import javax.xml.bind.annotation.XmlElement;
import javax.xml.bind.annotation.XmlRootElement;
import java.util.List;
@XmlRootElement(name = "MediaInfo")
public class MediaInfo {
private List<Track> track;
@XmlElement(name = "track")
public List<Track> getTrack() {
return track;
}
public void setTrack(List<Track> track) {
this.track = track;
}
}
Track.java (Represents a single track - General, Video, Audio, etc.)
package com.example.mediainfo;
import javax.xml.bind.annotation.XmlAttribute;
import javax.xml.bind.annotation.XmlElement;
import java.util.List;
public class Track {
private String type;
private List<String> tag;
@XmlAttribute
public String getType() {
return type;
}
public void setType(String type) {
this.type = type;
}
@XmlElement(name = "tag")
public List<String> getTag() {
return tag;
}
public void setTag(List<String> tag) {
this.tag = tag;
}
// Helper methods to get specific values by key
public String get(String key) {
if (tag != null) {
int index = tag.indexOf(key);
if (index != -1 && index + 1 < tag.size()) {
return tag.get(index + 1);
}
}
return null;
}
// Convenience getters for common fields
public String getFormat() { return get("Format"); }
public String getCodec() { return get("CodecID"); }
public String getWidth() { return get("Width"); }
public String getHeight() { return get("Height"); }
public String getDuration() { return get("Duration"); }
public String getFrameRate() { return get("FrameRate"); }
public String getBitDepth() { return get("BitDepth"); }
public String getChannels() { return get("Channel(s)"); }
public String getSamplingRate() { return get("SamplingRate"); }
public String getBitRate() { return get("BitRate"); }
public String getOverallBitRate() { return get("OverallBitRate"); }
}
ObjectFactory.java (Required by JAXB)
package com.example.mediainfo;
import javax.xml.bind.annotation.XmlRegistry;
@XmlRegistry
public class ObjectFactory {
public MediaInfo createMediaInfo() {
return new MediaInfo();
}
public Track createTrack() {
return new Track();
}
}
Step 4: Run and Test
- Make sure the
MediaInfo.exe(orMediaInfo) is in thelib/media_info/directory relative to your project root. - Update the path in
MediaInfoParser.javaif necessary. - Update the path to your media file in the
mainmethod. - Run the
MediaInfoParser.javafile.
You should see the metadata printed to the console.
Alternative: Using a Wrapper Library
If you prefer not to handle the process yourself, you can use a pre-built wrapper. A popular one is mediainfo-library.
Maven Dependency:
<dependency>
<groupId>org.mediainfo</groupId>
<artifactId>mediainfo-library</artifactId>
<version>1.0</version> <!-- Check for the latest version -->
</dependency>
Usage Example:
import org.mediainfo.Library;
import org.mediainfo.MediaInfo;
public class WrapperExample {
public static void main(String[] args) {
// The library will automatically try to locate the native MediaInfo library
MediaInfo mediaInfo = new MediaInfo();
// Option 1: Load from a file
mediaInfo.open(new File("C:/path/to/your/video.mp4"));
// Option 2: Load from memory (e.g., a byte array)
// byte[] fileBytes = ...;
// mediaInfo.openBuffer(fileBytes, fileBytes.length);
// Get formatted text output (similar to the command line)
System.out.println("--- Formatted Output ---");
System.out.println(mediaInfo Inform());
// Get specific details
System.out.println("\n--- Specific Details ---");
System.out.println("Video Codec: " + mediaInfo.get(MediaInfo.StreamKind.Video, 0, "Codec"));
System.out.println("Audio Codec: " + mediaInfo.get(MediaInfo.StreamKind.Audio, 0, "Codec"));
mediaInfo.close();
}
}
Note: This wrapper still requires the native MediaInfo library (.dll or .so) to be on the system path or in a location the library can find. The documentation for the wrapper will provide details on this.
