CodecMedia is a Java 17 library for inspecting and handling media files with no runtime dependencies declared in the Maven project.
The current implementation focuses on:
- Media probing for selected audio, image, and video/container formats
- File validation with optional strict parser checks
- Basic metadata read/write workflows
- Limited conversion routes that are implemented in Java or through JDK APIs
- Playback workflow routing for Java Sound and desktop-open use cases
CodecMedia is not a complete transcoding framework. Unsupported routes fail explicitly instead of silently shelling out to external tools.
- Overview
- Features
- Current Status
- Installation
- Quick Start
- Configuration
- Architecture
- Supported Features
- Limitations
- Development
- Testing
- Roadmap
- Contributing
- License
Use CodecMedia when you need a small Java API for common media-file checks and simple processing tasks.
The public entry point is CodecMedia.createDefault(), which returns a CodecMediaEngine.
Main API methods:
get(Path)- alias forprobe(Path)probe(Path)- detect media type, MIME type, extension, duration, streams, and format-specific tagsvalidate(Path, ValidationOptions)- validate file existence, size limits, and optional strict parser checksreadMetadata(Path)- read base probe metadata plus supported embedded or sidecar metadatawriteMetadata(Path, Metadata)- write supported embedded metadata, or a sidecar file when embedded writes are not supportedextractAudio(Path, Path, AudioExtractOptions)- copy supported audio input into an output directory without transcodingconvert(Path, Path, ConversionOptions)- run an implemented conversion routeplay(Path, PlaybackOptions)- attempt dry-run, Java sampled playback, or desktop-open playback
- Java 17 API using
Pathand Java records - Maven artifact:
me.tamkungz.codecmedia:codecmedia:1.2.1 - No runtime dependencies declared in
pom.xml - Parser-backed probing for selected media formats
- Strict validation for supported parsers
- Embedded metadata support for selected audio formats
- Sidecar metadata fallback using
.codecmedia.properties - Conversion hub with explicit route handling
- CI coverage for Java 17 and Java 21
CodecMedia is usable for the implemented routes listed in this README, but the project is still evolving.
Important status notes:
- Current version:
1.2.1 - Minimum Java version: 17
- Build tool: Maven
- Default implementation class is still named
StubCodecMediaEngine; this name does not mean every feature is a stub, but it is a sign that the implementation is still being consolidated. - MP3 decoding through the
pure-javaorlayer3backend is experimental. - General-purpose transcoding is not implemented.
- Some image conversion routes depend on ImageIO reader/writer support available in the runtime.
- JDK 17 or newer
- Maven 3.9 or newer if building from source
Add the dependency to your project:
<dependency>
<groupId>me.tamkungz.codecmedia</groupId>
<artifactId>codecmedia</artifactId>
<version>1.2.1</version>
</dependency>dependencies {
implementation("me.tamkungz.codecmedia:codecmedia:1.2.1")
}git clone https://github.com/CodecMediaLib/codecmedia-java.git
cd codecmedia-java
mvn -Dgpg.skip=true clean verify-Dgpg.skip=true is useful for local development because the project signs release artifacts during verify.
import java.nio.file.Path;
import me.tamkungz.codecmedia.CodecMedia;
import me.tamkungz.codecmedia.CodecMediaEngine;
import me.tamkungz.codecmedia.options.ValidationOptions;
public class ProbeExample {
public static void main(String[] args) throws Exception {
CodecMediaEngine media = CodecMedia.createDefault();
Path input = Path.of(args.length > 0 ? args[0] : "src/test/resources/png_test.png");
var probe = media.probe(input);
System.out.println(probe.mimeType());
System.out.println(probe.mediaType());
System.out.println(probe.primaryCodec().orElse("unknown"));
var validation = media.validate(input, ValidationOptions.defaults());
System.out.println("valid=" + validation.valid());
}
}import java.nio.file.Path;
import me.tamkungz.codecmedia.CodecMedia;
import me.tamkungz.codecmedia.options.ConversionOptions;
public class ImageConvertExample {
public static void main(String[] args) throws Exception {
var media = CodecMedia.createDefault();
var result = media.convert(
Path.of("src/test/resources/png_test.png"),
Path.of("target/example-output.jpg"),
new ConversionOptions("jpg", "balanced", true)
);
System.out.println(result.outputFile());
System.out.println(result.format());
}
}import java.nio.file.Files;
import java.nio.file.Path;
import java.nio.file.StandardCopyOption;
import java.util.Map;
import me.tamkungz.codecmedia.CodecMedia;
import me.tamkungz.codecmedia.model.Metadata;
public class MetadataExample {
public static void main(String[] args) throws Exception {
var media = CodecMedia.createDefault();
Path input = Path.of("src/test/resources/png_test.png");
Path workFile = Path.of("target/metadata-example.png");
Files.createDirectories(workFile.getParent());
Files.copy(input, workFile, StandardCopyOption.REPLACE_EXISTING);
media.writeMetadata(workFile, new Metadata(Map.of("title", "Example")));
Metadata metadata = media.readMetadata(workFile);
System.out.println(metadata.entries());
}
}For formats without embedded write support, metadata is written to a sibling sidecar file named <file>.codecmedia.properties.
Configuration is passed through option records.
strict- whentrue, runs parser-level checks for supported formatsmaxBytes- rejects files larger than this size when greater than0ValidationOptions.defaults()- non-strict validation with a 500 MiB size limit
Example:
var options = new ValidationOptions(true, 64L * 1024L * 1024L);targetFormat- required output format, such asjpg,wav,pcm, orm4apreset- route-specific string, defaulting tobalancedoverwrite- controls whether existing output files may be replacedConversionOptions.defaults()- defaults to target formatm4a, presetbalanced, andoverwrite=false
Known preset tokens:
pcm -> wav:sr=<sampleRate>,ch=<channels>,bits=<bitsPerSample>mp3 -> pcmandmp3 -> wav:decoder=javasound,decoder=pure-java, ordecoder=layer3
targetFormat- must match the source format in the current implementationbitrateKbps- accepted by the options record, but no transcoding is performed byextractAudiostreamIndex- accepted by the options record, but multi-stream extraction is not implementedAudioExtractOptions.defaults()- uses source format resolution in the engine
dryRun- returns a successful playback result without opening or playing the fileallowExternalApp- allows fallback to the operating system default applicationPlaybackOptions.defaults()-dryRun=false,allowExternalApp=true
CodecMedia is organized around a small public facade and internal format-specific components.
CodecMediacreates the default engine.CodecMediaEnginedefines the public API contract.StubCodecMediaEnginecoordinates probing, validation, metadata, extraction, conversion, and playback.- Internal parser packages handle audio, image, and container formats.
DefaultConversionHubroutes conversions to specific converters or explicit unsupported-route failures.- Image conversion uses JDK
ImageIOand any reader/writer plugins present at runtime. - Audio playback uses Java Sound for WAV/AIFF-family inputs and can fall back to
java.awt.Desktop.
Probe results include the detected MIME type, extension, media type, duration when available, stream information, and format-specific tags.
Supported probe formats:
- Audio:
mp3,ogg,wav,aif,aiff,aifc,flac,m4a - Images:
png,jpg,jpeg,webp,bmp,tif,tiff,heic,heif,avif - Video/containers:
mov,mp4,webm
Validation supports:
- File existence checks
- Maximum file size checks
- Optional strict parser checks for
mp3,ogg,wav,aif,aiff,aifc,flac,png,jpg,jpeg,mov,mp4,m4a,webm,webp,bmp,tif,tiff,heic,heif, andavif
Strict validation currently reads the full file and is limited to files up to 32 MiB.
readMetadata always includes base probe fields:
mimeTypeextensionmediaType
Embedded metadata support:
- WAV: read/write RIFF
LIST/INFO - AIFF/AIF/AIFC: read/write
NAME,AUTH,(c), andANNOtext chunks - MP3: read/write ID3v1
- OGG: read Vorbis/Opus comments
- FLAC: read Vorbis comments
Sidecar metadata support:
- Unsupported embedded write formats use
<file>.codecmedia.properties. - Embedded metadata is treated as canonical where supported.
- Sidecar values are merged as fallback values for non-core keys.
Current audio extraction is a copy workflow:
- Input must be detected as
MediaType.AUDIO. - Output is written as
<baseName>_audio.<sourceExtension>inside the output directory. - Requested target format must match the source format.
- Format conversion during extraction is not implemented.
Implemented conversion routes:
- Same-format copy for matching source and target extensions
- Image-to-image conversion for
png,jpg,jpeg,webp,bmp,tif,tiff,heic,heif, andavif wav -> pcmby extracting the WAVdatachunk from PCM WAV filespcm -> wavby wrapping raw PCM bytes in a WAV containermp3 -> pcmthrough a selected decoder backendmp3 -> wavthrough a selected decoder backend- Java Sound audio output to
wav,aif,aiff,aifc, orauwhen the runtime supports the source and target combination mp4 -> m4aandmov -> m4aremux when an M4A-compatible audio track is present
Runtime-dependent routes:
- WebP image decode/encode requires ImageIO WebP support.
- TIFF image decode/encode may require ImageIO TIFF support, depending on the JDK/runtime.
- HEIF, HEIC, and AVIF image decode/encode require compatible ImageIO support.
- Java Sound audio conversion depends on audio service providers available in the runtime.
Playback supports:
- Dry-run mode for all known media types
- Java sampled playback for WAV/AIFF-family audio when Java Sound can open the file
- Desktop-open fallback through
java.awt.Desktopwhen enabled and supported by the platform
- Probe output is technical media information, not a complete metadata catalog.
- ID3v2, album art/APIC extraction, and advanced tag families are not fully supported.
- General compressed audio transcoding, such as
mp3 -> ogg, is not implemented. - Generic video-to-audio conversion is not implemented, except the implemented MP4/MOV to M4A remux route.
- Video-to-video conversion is not implemented.
- Audio-to-image album-art extraction is not implemented.
extractAudiodoes not transcode and does not select arbitrary streams.- TIFF probing reads the first IFD/image only.
- WebP probing reports an assumed bit depth for VP8, VP8L, and VP8X when deeper profile metadata is not parsed.
- HEIF, HEIC, AVIF, WebP, and TIFF image conversion depends on runtime ImageIO support.
- Strict validation is limited to files up to 32 MiB.
Clone and verify the project locally:
git clone https://github.com/CodecMediaLib/codecmedia-java.git
cd codecmedia-java
mvn -Dgpg.skip=true clean verifyUseful commands:
mvn -Dgpg.skip=true test
mvn -Dgpg.skip=true -DskipTests package
mvn -Dgpg.skip=true clean verifyProject layout:
src/main/java/me/tamkungz/codecmedia- public API and implementationsrc/main/java/me/tamkungz/codecmedia/internal- parsers, converters, and engine internalssrc/test/java- unit and facade testssrc/test/resources- test fixtures.github/workflows- CI and deeper test workflows
Run the full test suite:
mvn -Dgpg.skip=true testRun the same verify phase used by CI without signing artifacts:
mvn -Dgpg.skip=true clean verifyRun focused tests:
mvn -Dgpg.skip=true -Dtest=CodecMediaFacadeTest test
mvn -Dgpg.skip=true -Dtest=CodecMediaPlayTest test
mvn -Dgpg.skip=true -Dtest=Mp3PcmWavConverterTest testCI currently verifies Java 17 and Java 21 with:
mvn -B -Dgpg.skip=true clean verifyImplemented features and planned work are separated below to avoid implying unsupported behavior.
- Probing for the supported audio, image, and video/container formats listed above
- Strict parser validation for supported formats
- Embedded metadata read/write for WAV, AIFF-family files, and MP3 ID3v1
- Embedded metadata read for OGG and FLAC comments
- Sidecar metadata fallback
- Limited conversion routes listed in Conversion
- Dry-run, Java sampled, and desktop-open playback workflows
- Generic video-to-audio conversion route
- Audio-to-image album-art extraction route
- Video-to-video conversion route
- Broader audio transcoding support beyond Java Sound, WAV/PCM, and MP3 decode routes
- TODO: Document the exact metadata key mapping for each embedded metadata format.
- TODO: Document the supported ImageIO plugin combinations used for WebP, TIFF, HEIF, HEIC, and AVIF conversion.
- TODO: Document release and publishing steps for maintainers.
- TODO: Decide whether
StubCodecMediaEngineshould be renamed now that it contains implemented behavior.
Contributions should keep documentation aligned with implemented behavior.
Before opening a pull request:
- Run
mvn -Dgpg.skip=true test. - Add or update tests for parser, conversion, metadata, or facade behavior changes.
- Update this README and
CHANGELOG.mdwhen user-visible behavior changes. - Mark incomplete or runtime-dependent behavior clearly.
- Avoid documenting planned features as supported features.
Issues and pull requests are tracked at:
CodecMedia is licensed under the Apache License 2.0. See LICENSE for details.
