<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom" xmlns:dc="http://purl.org/dc/elements/1.1/">
  <channel>
    <title>DEV Community: TamKungZ_</title>
    <description>The latest articles on DEV Community by TamKungZ_ (@tamkungz_).</description>
    <link>https://dev.to/tamkungz_</link>
    <image>
      <url>https://media2.dev.to/dynamic/image/width=90,height=90,fit=cover,gravity=auto,format=auto/https:%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Fuser%2Fprofile_image%2F3824240%2F2b8caa35-25a0-4f5b-a195-d1d486c486ce.png</url>
      <title>DEV Community: TamKungZ_</title>
      <link>https://dev.to/tamkungz_</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://dev.to/feed/tamkungz_"/>
    <language>en</language>
    <item>
      <title>How a Minecraft mod led me to build my own Java media library from scratch</title>
      <dc:creator>TamKungZ_</dc:creator>
      <pubDate>Sat, 14 Mar 2026 17:11:35 +0000</pubDate>
      <link>https://dev.to/tamkungz_/how-a-minecraft-mod-led-me-to-build-my-own-java-media-library-from-scratch-1m60</link>
      <guid>https://dev.to/tamkungz_/how-a-minecraft-mod-led-me-to-build-my-own-java-media-library-from-scratch-1m60</guid>
      <description>&lt;p&gt;I was building a Minecraft mod — one that could play MP3 files directly through OpenAL instead of using Minecraft's built-in audio API.&lt;/p&gt;

&lt;p&gt;To stream audio that way, I needed something that could decode MP3 at a low level. I like digging into obscure or old-school tools, so I found &lt;strong&gt;Zoom JLayer&lt;/strong&gt; — a pure-Java MP3 decoder from the early 2000s. It looked perfect.&lt;/p&gt;

&lt;p&gt;Except it only worked on &lt;em&gt;some&lt;/em&gt; MP3 files.&lt;/p&gt;

&lt;p&gt;That bugged me. Same extension. Same player. Completely different behavior.&lt;/p&gt;

&lt;p&gt;So I dug into JLayer's source code (someone had dumped it on GitHub) and saw something I'd never really thought about before — MP3 files aren't all the same. There are different bitrate modes — CBR, VBR — frame headers, side information, and other structures hidden inside the bytes.&lt;/p&gt;

&lt;p&gt;That sent me down a rabbit hole. Where do these values actually come from?&lt;/p&gt;

&lt;p&gt;Turns out — &lt;strong&gt;the bytes themselves.&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Once I started reading raw bytes directly, I couldn't stop. I began studying how media file formats work at the byte level. At the time though, I just shipped a custom fork of JLayer so the mod could work and moved on.&lt;/p&gt;




&lt;p&gt;Later, I needed WAV support. Then format conversion.&lt;/p&gt;

&lt;p&gt;I looked at Java wrappers around FFmpeg — they exist — but they all felt heavy. Most depend on native binaries or large external toolchains. I wanted something different: zero dependencies, pure Java, and as lightweight as possible.&lt;/p&gt;

&lt;p&gt;So I built &lt;strong&gt;CodecMedia&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;What started as a small personal utility for a Minecraft mod slowly turned into a media library that probes and validates file formats by parsing their actual byte structure directly — no native tools involved.&lt;/p&gt;




&lt;h2&gt;
  
  
  What it looks like
&lt;/h2&gt;

&lt;p&gt;Add the dependency:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight xml"&gt;&lt;code&gt;&lt;span class="nt"&gt;&amp;lt;dependency&amp;gt;&lt;/span&gt;
    &lt;span class="nt"&gt;&amp;lt;groupId&amp;gt;&lt;/span&gt;me.tamkungz.codecmedia&lt;span class="nt"&gt;&amp;lt;/groupId&amp;gt;&lt;/span&gt;
    &lt;span class="nt"&gt;&amp;lt;artifactId&amp;gt;&lt;/span&gt;codecmedia&lt;span class="nt"&gt;&amp;lt;/artifactId&amp;gt;&lt;/span&gt;
    &lt;span class="nt"&gt;&amp;lt;version&amp;gt;&lt;/span&gt;1.1.1&lt;span class="nt"&gt;&amp;lt;/version&amp;gt;&lt;/span&gt;
&lt;span class="nt"&gt;&amp;lt;/dependency&amp;gt;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Probe an audio file:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight java"&gt;&lt;code&gt;&lt;span class="nc"&gt;CodecMediaEngine&lt;/span&gt; &lt;span class="n"&gt;engine&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nc"&gt;CodecMedia&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;createDefault&lt;/span&gt;&lt;span class="o"&gt;();&lt;/span&gt;

&lt;span class="nc"&gt;ProbeResult&lt;/span&gt; &lt;span class="n"&gt;probe&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;engine&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;probe&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="nc"&gt;Path&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;of&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"song.mp3"&lt;/span&gt;&lt;span class="o"&gt;));&lt;/span&gt;
&lt;span class="nc"&gt;System&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;out&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;println&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="n"&gt;probe&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;mimeType&lt;/span&gt;&lt;span class="o"&gt;());&lt;/span&gt;       &lt;span class="c1"&gt;// audio/mpeg&lt;/span&gt;
&lt;span class="nc"&gt;System&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;out&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;println&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="n"&gt;probe&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;durationMillis&lt;/span&gt;&lt;span class="o"&gt;());&lt;/span&gt; &lt;span class="c1"&gt;// 213000&lt;/span&gt;
&lt;span class="nc"&gt;System&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;out&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;println&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="n"&gt;probe&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;streams&lt;/span&gt;&lt;span class="o"&gt;().&lt;/span&gt;&lt;span class="na"&gt;get&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="o"&gt;).&lt;/span&gt;&lt;span class="na"&gt;codec&lt;/span&gt;&lt;span class="o"&gt;());&lt;/span&gt;      &lt;span class="c1"&gt;// mp3&lt;/span&gt;
&lt;span class="nc"&gt;System&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;out&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;println&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="n"&gt;probe&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;streams&lt;/span&gt;&lt;span class="o"&gt;().&lt;/span&gt;&lt;span class="na"&gt;get&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="o"&gt;).&lt;/span&gt;&lt;span class="na"&gt;sampleRate&lt;/span&gt;&lt;span class="o"&gt;());&lt;/span&gt; &lt;span class="c1"&gt;// 44100&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Validate before using:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight java"&gt;&lt;code&gt;&lt;span class="nc"&gt;ValidationResult&lt;/span&gt; &lt;span class="n"&gt;validation&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;engine&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;validate&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;
    &lt;span class="nc"&gt;Path&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;of&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"song.mp3"&lt;/span&gt;&lt;span class="o"&gt;),&lt;/span&gt;
    &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nf"&gt;ValidationOptions&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="kc"&gt;true&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;64L&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt; &lt;span class="mi"&gt;1024L&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt; &lt;span class="mi"&gt;1024L&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt;
&lt;span class="o"&gt;);&lt;/span&gt;
&lt;span class="nc"&gt;System&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;out&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;println&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="n"&gt;validation&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;valid&lt;/span&gt;&lt;span class="o"&gt;());&lt;/span&gt;  &lt;span class="c1"&gt;// true&lt;/span&gt;
&lt;span class="nc"&gt;System&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;out&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;println&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="n"&gt;validation&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;errors&lt;/span&gt;&lt;span class="o"&gt;());&lt;/span&gt; &lt;span class="c1"&gt;// []&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Currently supports probing for &lt;strong&gt;MP3, OGG/Vorbis/Opus, WAV, FLAC, AIFF/AIFC&lt;/strong&gt;, and more.&lt;/p&gt;




&lt;p&gt;It's still a work in progress and I'm learning more about media formats as I go. But if you're working in Java and need media probing without pulling in a native dependency, you might find it useful.&lt;/p&gt;




&lt;p&gt;&lt;strong&gt;Note:&lt;/strong&gt; There are probably better tools out there for this. And yes, there are many alternatives.&lt;/p&gt;

&lt;p&gt;But I didn't build CodecMedia just to have a tool that works. I built it because I wanted to &lt;em&gt;understand&lt;/em&gt; how it works — to study the formats, read the bytes, and learn by actually building something real with that knowledge.&lt;/p&gt;

&lt;p&gt;CodecMedia is that experiment.&lt;/p&gt;

&lt;p&gt;👉 &lt;a href="https://central.sonatype.com/artifact/me.tamkungz.codecmedia/codecmedia" rel="noopener noreferrer"&gt;Maven Central&lt;/a&gt;&lt;br&gt;&lt;br&gt;
👉 &lt;a href="https://github.com/CodecMediaLib/codecmedia-java" rel="noopener noreferrer"&gt;GitHub&lt;/a&gt;&lt;/p&gt;

</description>
      <category>gamedev</category>
      <category>java</category>
      <category>programming</category>
      <category>sideprojects</category>
    </item>
  </channel>
</rss>
