Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
16 changes: 0 additions & 16 deletions .github/workflows/ant.yml

This file was deleted.

16 changes: 16 additions & 0 deletions .github/workflows/gradle.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
name: Java CI

on: [push]

jobs:
build:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- name: Set up JDK 8
uses: actions/setup-java@v4
with:
java-version: 8
distribution: temurin
- name: Run test suite with Gradle
run: ./gradlew test
6 changes: 2 additions & 4 deletions .gitignore
Original file line number Diff line number Diff line change
@@ -1,7 +1,6 @@
/.idea
*.iml

/ivy
/lib

/build
Expand All @@ -11,9 +10,8 @@
/dist
/javadoc

/FAKE_BD
/*.mkv
/bd.txt
/bd_title.txt

/todo.txt
.gradle/
build/
77 changes: 77 additions & 0 deletions CLAUDE.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,77 @@
# CLAUDE.md

This file provides guidance to Claude Code (claude.ai/code) when working with code in this repository.

## What This Project Is

A Java library that wraps [eac3to](https://www.videohelp.com/software/eac3to), a Windows CLI tool for scanning and demuxing MKV/M2TS files and Blu-ray directories. The library is Windows-only at runtime (requires `eac3to.exe`), but builds and tests run on any platform since tests mock the process runner.

## Build System

Gradle with wrapper. Source/target compatibility is Java 8. Set `JAVA_HOME` to Java 8 when building.

```bash
# Build the jar (compiles and runs tests)
JAVA_HOME=/usr/lib/jvm/java-1.8.0-openjdk-amd64 ./gradlew build

# Run all tests
JAVA_HOME=/usr/lib/jvm/java-1.8.0-openjdk-amd64 ./gradlew test

# Run a subset of tests (partial class-name match)
JAVA_HOME=/usr/lib/jvm/java-1.8.0-openjdk-amd64 ./gradlew test --tests "*Iso639*"

# Clean all build artifacts
JAVA_HOME=/usr/lib/jvm/java-1.8.0-openjdk-amd64 ./gradlew clean
```

## Publishing

Publishing to Maven Central (Sonatype) requires GPG signing and Sonatype credentials. Tokens are generated at central.sonatype.com.

```bash
# Publish snapshot (version must end in -SNAPSHOT)
JAVA_HOME=/usr/lib/jvm/java-1.8.0-openjdk-amd64 ./gradlew publishToSonatype \
-Ppublish.user=<token-user> \
-Ppublish.password=<token-password> \
-Psigning.gnupg.passphrase="<gpg-passphrase>"

# Publish release (remove -SNAPSHOT from version in build.gradle first)
JAVA_HOME=/usr/lib/jvm/java-1.8.0-openjdk-amd64 ./gradlew publishToSonatype closeAndReleaseSonatypeStagingRepository \
-Ppublish.user=<token-user> \
-Ppublish.password=<token-password> \
-Psigning.gnupg.passphrase="<gpg-passphrase>"

# Test publishing locally (no upload to Sonatype)
JAVA_HOME=/usr/lib/jvm/java-1.8.0-openjdk-amd64 ./gradlew publishToMavenLocal
```

Repository URLs configured in `build.gradle`:
- Snapshots: `https://central.sonatype.com/repository/maven-snapshots/`
- Staging: `https://ossrh-staging-api.central.sonatype.com/service/local/staging/deploy/maven2/`

## Architecture

### Entry Point

`FileScanner` (interface) → `Eac3toScanner` (sole implementation). Consumers instantiate `Eac3toScanner` with the path to `eac3to.exe` and an output directory.

### Parsing Flow

`Eac3toScanner` invokes eac3to via `ProcessRunner` (seam interface), then parses its stdout line-by-line using `StringLineIterator`. Parsed output is assembled into a `Video` containing a list of `Track` objects.

Eac3to output comes in two formats ("legacy" plain-English language names, "new" ISO 639-2 bracketed codes). `Iso639Language.fromToken()` normalizes both.

### Model

- `Video` → `List<Track>`
- `Track`: number, name (nullable quoted string), `Format`, `Iso639Language`
- `Format`: name string + `FormatType` enum (AUDIO/VIDEO/SUBTITLES/CHAPTERS)
- `Iso639Language`: full ISO 639-2 enum; `fromToken(String)` accepts plain names, aliases, bracketed codes (`[eng]`), bare codes — case-insensitive, whitespace-trimmed; `UNDETERMINED` sentinel for absent/unknown language

### Format→Extension Mapping

`src/main/resources/eac3to-format-extensions.json` maps format names to output file extensions and optional flags. Loaded by `FormatExtensionConfig`. Formats with multiple configs (DTS-HD Master Audio, TrueHD/AC3) produce multiple output files per track. VobSub tracks are silently skipped during demux (extension unknown).

### Testing

Tests mock `ProcessRunner` with fixture strings representing real eac3to output, so no eac3to binary is needed. `Eac3toScanner` exposes a package-private constructor accepting a `ProcessRunner` for this purpose.
23 changes: 4 additions & 19 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -12,9 +12,9 @@ Video metadata = scanner.scanAndParseFile(new File("c:\\mkvs\\MyMovie.mkv"));
~~~~

`metadata` now contains a list of the tracks found in the mkv file. Each track object (in `metadata.getTracks()`) contains information about the track, such as:
- name, plaintext label, if it has one
- format name (AC-3, H-264, PGS, etc)
- format type (Audio, Video, Subtitles, Chapters)
- name: plaintext label, if it has one
- format name: (AC-3, H-264, PGS, etc)
- format type: (Audio, Video, Subtitles, Chapters)
- language

### demuxing:
Expand All @@ -28,19 +28,4 @@ demuxed tracks are output into the directory specified in the Eac3toScanner cons

### adding as a dependency

Page on [search.maven.org](http://search.maven.org/#artifactdetails%7Ccom.adashrod.mkvscanner%7Cmkvscanner%7C1.0.0%7Cpom)

Page on [mvnrepository.com](http://mvnrepository.com/artifact/com.adashrod.mkvscanner/mkvscanner)

##### Maven:
~~~~
<dependency>
<groupId>com.adashrod.mkvscanner</groupId>
<artifactId>mkvscanner</artifactId>
<version>1.1.0</version>
</dependency>
~~~~
##### Ivy:
~~~~
<dependency org="com.adashrod.mkvscanner" name="mkvscanner" rev="1.1.0" />
~~~~
[Maven Central](http://search.maven.org/#artifactdetails%7Ccom.adashrod.mkvscanner%7Cmkvscanner%7C2.0.0%7Cpom)
91 changes: 91 additions & 0 deletions build.gradle
Original file line number Diff line number Diff line change
@@ -0,0 +1,91 @@
plugins {
id 'java-library'
id 'maven-publish'
id 'signing'
id 'io.github.gradle-nexus.publish-plugin' version '1.3.0'
}

group = 'com.adashrod.mkvscanner'
version = '2.0.0'

java {
sourceCompatibility = JavaVersion.VERSION_1_8
targetCompatibility = JavaVersion.VERSION_1_8
withSourcesJar()
withJavadocJar()
}

repositories {
mavenCentral()
}

dependencies {
implementation 'org.slf4j:slf4j-api:1.7.25'
implementation 'com.fasterxml.jackson.core:jackson-core:2.7.0'
implementation 'com.fasterxml.jackson.core:jackson-databind:2.7.0'

testImplementation 'org.junit.jupiter:junit-jupiter-engine:5.4.2'
testImplementation 'org.junit.platform:junit-platform-engine:1.4.2'
testImplementation 'org.mockito:mockito-core:2.27.0'
testImplementation 'org.mockito:mockito-junit-jupiter:2.27.0'
}

test {
useJUnitPlatform()

testLogging {
events "passed", "skipped", "failed"
exceptionFormat "full"
showStackTraces true
showCauses true
showStandardStreams false
}
}

publishing {
publications {
mavenJava(MavenPublication) {
from components.java
pom {
name = 'MkvScanner'
description = 'MkvScanner is a java API wrapper for eac3to'
url = 'https://www.github.com/adashrod/MkvScanner'
licenses {
license {
name = 'MIT License'
url = 'https://opensource.org/licenses/MIT'
distribution = 'repo'
}
}
scm {
url = 'https://www.github.com/adashrod/MkvScanner'
connection = 'scm:git:git@github.com:adashrod/MkvScanner.git'
developerConnection = 'scm:git:git@github.com:adashrod/MkvScanner.git'
}
developers {
developer {
name = 'Aaron Rodriguez'
email = 'adashrod@gmail.com'
url = 'https://www.github.com/adashrod'
}
}
}
}
}
}

nexusPublishing {
repositories {
sonatype {
nexusUrl = uri('https://ossrh-staging-api.central.sonatype.com/service/local/')
snapshotRepositoryUrl = uri('https://central.sonatype.com/repository/maven-snapshots/')
username = findProperty('publish.user') ?: ''
password = findProperty('publish.password') ?: ''
}
}
}

signing {
useGpgCmd()
sign publishing.publications.mavenJava
}
Loading
Loading