Developers guide lines - a-schild/jave2 GitHub Wiki
Developers guide lines
For working on JAVE2 itself. If you are using the library, see Usage.
Building
mvn clean install
The library is compiled for Java 8 (maven.compiler.source 1.8), so it stays usable
on old runtimes, but it is built and tested with a newer JDK, currently 17 in CI. One
module, jave-core-test-java11, targets 11 instead, for tests that need APIs Java 8 does
not have.
Keep to Java 8 language level in jave-core. It is the one constraint that is easy to
break without noticing, since a modern JDK compiles most newer syntax happily until the
source level rejects it.
Layout
| Module | What it is |
|---|---|
jave-core |
All the java code. No binaries, platform independent |
jave-core-test |
The test suite, which runs against real media files |
jave-core-test-java11 |
Tests that need Java 11 |
jave-bom |
Bill of materials, versions only |
jave-all-deps |
Core plus every platform binary |
jave-example |
A small runnable sample |
jave-nativebin-* |
One module per platform, each carrying one ffmpeg executable |
The native binary module directories do not all match their artifact ids: the directories
jave-nativebin-arm64 and jave-nativebin-arm32 publish as
jave-nativebin-linux-arm64 and jave-nativebin-linux-arm32.
The binaries themselves are large and are committed to the repository. Be careful with
git add -A in a dirty tree, since it is easy to stage a few hundred megabytes of
executables by accident.
Tests
mvn -pl jave-core-test test
The tests transcode real files, so they are slower than unit tests and they depend on the
bundled ffmpeg actually working on the machine. Some tests reach out to remote sample
files and skip themselves, via Assumptions.assumeTrue, when the sample cannot be
fetched, so a green run offline may be a smaller run than it looks.
BundledFFmpegVersionTest pins the version of the bundled ffmpeg, so an upgrade cannot
land half done without something failing. Two limits are worth knowing: it checks only the
package for the machine it runs on, keyed by os.arch, and CI runs on ubuntu-latest
only, so the windows and macOS packages are not covered by an ordinary CI run. A package
that is deliberately behind goes in the KNOWINGLY_BEHIND map rather than weakening the
assertion.
File size assertions use assertFileSizeNear rather than an exact figure, because encoder
output varies slightly between builds of ffmpeg.
Branches
masteris the default branch and holds releases.developcarries-SNAPSHOTversions. Pushing to it publishes a snapshot.
Note that workflow_dispatch only offers a workflow that exists on the default branch,
so a new workflow has to reach master before it can be triggered by hand.
The ffmpeg binaries
The windows and macOS binaries come from publishers. The linux binaries are built from
source in CI, by .github/workflows/build-linux-ffmpeg.yml and
.github/scripts/build-ffmpeg-static.sh, for amd64, arm64 and arm32.
They are fully static musl builds, which is the point: they carry no libc dependency at all, so they run on any linux including musl based images, rather than requiring a glibc at least as new as the build machine's. Every library version in that script is pinned, so a build is reproducible and an upstream release cannot change the output silently.
The workflow has a parity gate: it compares the encoders in the new binary against the
expected list and fails on any unexplained loss, with a per architecture list of losses
that are known and accepted. libx265 is not built for arm32.
A few things about that script are load bearing and look like style:
make -jandmake installare separate commands. Chained with&&underset -e, a failure in the first is swallowed, which once let a broken library through.- Encoder lists are written to files rather than piped into
grep -qorhead, because withpipefaila closed pipe gives SIGPIPE and reads as a failure.
Versioning
Since 2.6.0 this project follows semantic versioning 2.0.0. Given MAJOR.MINOR.PATCH, increment the
- MAJOR version for incompatible API changes,
- MINOR version for functionality added in a backwards compatible way,
- PATCH version for backwards compatible bug fixes.
Removing a published artifact counts as breaking, which is why dropping the 32 bit x86 packages made 4.0.0 rather than 3.7.0.
Releasing
Publishing goes to Maven Central through the
Sonatype Central Portal with
central-publishing-maven-plugin. The old OSSRH service has been retired by Sonatype.
- A push to
developpublishes a snapshot, while the poms carry-SNAPSHOT. - Creating a GitHub release publishes the release, auto released by the plugin.
The required secrets are listed in the README.
When bumping versions across the poms, do not do it with a blind search and replace on
4.0.0: <modelVersion>4.0.0</modelVersion> is not the project version, and rewriting it
makes maven refuse to read the pom at all.
Give every GitHub release real notes describing the user facing changes, and update Changelog.md in the same change as the work, not afterwards.
Documentation
The wiki and Examples.md in the repository carry the same content and are meant to stay
in step. Java snippets in the documentation are worth compiling against jave-core before
publishing them, which is how six wrong API calls were caught in the 4.0.0 rewrite.