### Shorten AAC Track by Cropping Source: https://github.com/sannies/mp4parser/blob/master/README.md Remove samples from the beginning of an AAC track to shorten its duration, useful for audio synchronization. This example removes the first sample, shortening the track by approximately 22ms. ```java AACTrackImpl aacTrackOriginal = new AACTrackImpl(new FileDataSourceImpl("audio.aac")); // removes the first sample and shortens the AAC track by ~22ms CroppedTrack aacTrackShort = new CroppedTrack(aacTrackOriginal, 1, aacTrack.getSamples().size()); ``` -------------------------------- ### Build Standard MP4 with DefaultMp4Builder Source: https://context7.com/sannies/mp4parser/llms.txt Creates a standard MP4 file with a single moov box followed by mdat, interleaving chunks from all tracks. Allows customization of chunk boundaries using a Fragmenter, with a default of 2 seconds. Use when fragmented output is not required. ```java import org.mp4parser.Container; import org.mp4parser.muxer.Movie; import org.mp4parser.muxer.builder.DefaultFragmenterImpl; import org.mp4parser.muxer.builder.DefaultMp4Builder; import org.mp4parser.muxer.container.mp4.MovieCreator; import java.io.RandomAccessFile; import java.nio.channels.FileChannel; Movie movie = MovieCreator.build("source.mp4"); DefaultMp4Builder builder = new DefaultMp4Builder(); builder.setFragmenter(new DefaultFragmenterImpl(4)); // 4-second chunks Container out = builder.build(movie); try (FileChannel fc = new RandomAccessFile("output.mp4", "rw").getChannel()) { out.writeContainer(fc); fc.truncate(fc.position()); // trim any pre-existing file data } ``` -------------------------------- ### Create H.264 and AAC Track Objects Source: https://github.com/sannies/mp4parser/blob/master/README.md Wrap raw H.264 video and AAC audio files into their respective Track implementations using FileDataSourceImpl. ```java H264TrackImpl h264Track = new H264TrackImpl(new FileDataSourceImpl("video.h264")); AACTrackImpl aacTrack = new AACTrackImpl(new FileDataSourceImpl("audio.aac")); ``` -------------------------------- ### Path.getPath / Path.getPaths - XPath-style box navigation Source: https://context7.com/sannies/mp4parser/llms.txt The `Path` class offers a concise XPath-like syntax for navigating the nested ISO box hierarchy within an MP4 file. It allows for easy selection of specific boxes based on their type and index. ```APIDOC ## Path.getPath / Path.getPaths ### Description Provides a concise path expression syntax (similar to XPath) for navigating the nested ISO box hierarchy. Paths are slash-separated four-character box type codes; `[n]` selects a specific index among siblings of the same type. ### Method `Path.getPath(IsoFile isoFile, String pathExpression)` `Path.getPaths(IsoFile isoFile, String pathExpression)` ### Parameters #### Path Parameters - **isoFile** (IsoFile) - Required - The `IsoFile` object to navigate within. - **pathExpression** (String) - Required - The XPath-style path expression (e.g., `moov[0]/trak[0]/mdia[0]/minf[0]/stbl[0]/stsd[0]/avc1[0]/avcC[0]`). ### Request Example ```java import org.mp4parser.IsoFile; import org.mp4parser.boxes.apple.AppleNameBox; import org.mp4parser.boxes.iso14496.part15.AvcConfigurationBox; import org.mp4parser.tools.Path; IsoFile isoFile = new IsoFile("video.mp4"); // Navigate to Apple title metadata AppleNameBox nameBox = Path.getPath(isoFile, "moov[0]/udta[0]/meta[0]/ilst/©nam"); if (nameBox != null) { System.out.println("Title: " + nameBox.getValue()); } // Find H.264 configuration in the first video track AvcConfigurationBox avcC = Path.getPath(isoFile, "moov[0]/trak[0]/mdia[0]/minf[0]/stbl[0]/stsd[0]/avc1[0]/avcC[0]"); if (avcC != null) { System.out.println("NAL length size: " + (avcC.getLengthSizeMinusOne() + 1)); System.out.println("SPS count: " + avcC.getSequenceParameterSets().size()); } isoFile.close(); ``` ### Response #### Success Response (Box Type) - Returns the specific box found at the given path, or `null` if the path does not exist. #### Response Example ``` Title: My Awesome Video NAL length size: 4 SPS count: 1 ``` ``` -------------------------------- ### MovieCreator.build - Read an existing MP4 file Source: https://context7.com/sannies/mp4parser/llms.txt The `MovieCreator.build(String filePath)` method is the primary entry point for opening and parsing an existing MP4 file. It returns a `Movie` object that provides access to all tracks and their metadata within the file. ```APIDOC ## MovieCreator.build ### Description Reads an existing MP4 file and parses its ISO box structure into a `Movie` object, providing access to all tracks and their metadata. ### Method `MovieCreator.build(String filePath)` ### Parameters #### Path Parameters - **filePath** (String) - Required - The path to the MP4 file to be read. ### Request Example ```java import org.mp4parser.muxer.Movie; import org.mp4parser.muxer.Track; import org.mp4parser.muxer.container.mp4.MovieCreator; // Open and inspect an existing MP4 Movie movie = MovieCreator.build("input.mp4"); for (Track track : movie.getTracks()) { System.out.println("Handler : " + track.getHandler()); // "vide", "soun", "text", ... System.out.println("Samples : " + track.getSamples().size()); System.out.println("Timescale: " + track.getTrackMetaData().getTimescale()); System.out.println("Duration : " + track.getDuration() + " ticks"); } ``` ### Response #### Success Response (Movie) - **Movie** - An object representing the parsed MP4 file, containing all tracks and metadata. #### Response Example ``` Handler : vide Samples : 1800 Timescale: 90000 Duration : 162000000 ticks ``` ``` -------------------------------- ### XPath-style Box Navigation with Path Source: https://context7.com/sannies/mp4parser/llms.txt Utilize the Path class for concise, XPath-like navigation of the nested ISO box hierarchy in MP4 files. Paths use slash-separated four-character box type codes. ```java import org.mp4parser.IsoFile; import org.mp4parser.boxes.apple.AppleNameBox; import org.mp4parser.boxes.iso14496.part15.AvcConfigurationBox; import org.mp4parser.tools.Path; IsoFile isoFile = new IsoFile("video.mp4"); // Navigate to Apple title metadata AppleNameBox nameBox = Path.getPath(isoFile, "moov[0]/udta[0]/meta[0]/ilst/©nam"); if (nameBox != null) { System.out.println("Title: " + nameBox.getValue()); } // Find H.264 configuration in the first video track AvcConfigurationBox avcC = Path.getPath(isoFile, "moov[0]/trak[0]/mdia[0]/minf[0]/stbl[0]/stsd[0]/avc1[0]/avcC[0]"); if (avcC != null) { System.out.println("NAL length size: " + (avcC.getLengthSizeMinusOne() + 1)); System.out.println("SPS count: " + avcC.getSequenceParameterSets().size()); } isoFile.close(); ``` -------------------------------- ### Low-Level ISO Box Access with IsoFile Source: https://context7.com/sannies/mp4parser/llms.txt Use IsoFile for direct read access to the raw box tree of an MP4 file. This is useful for inspecting or modifying ISO structures without higher-level abstractions. ```java import org.mp4parser.IsoFile; import org.mp4parser.boxes.iso14496.part12.MovieBox; // Open file and read duration directly from the movie header box IsoFile isoFile = new IsoFile("video.mp4"); MovieBox moov = isoFile.getMovieBox(); double durationSeconds = (double) moov.getMovieHeaderBox().getDuration() / moov.getMovieHeaderBox().getTimescale(); System.out.println("Duration: " + durationSeconds + "s"); // Iterate over all top-level boxes for (var box : isoFile.getBoxes()) { System.out.println(box.getType() + " size=" + box.getSize()); // e.g.: ftyp size=24, moov size=143210, mdat size=48291870 } isoFile.close(); ``` -------------------------------- ### IsoFile - Low-level ISO box access Source: https://context7.com/sannies/mp4parser/llms.txt The `IsoFile` class provides direct read access to the raw box tree of an MP4/ISO file. It is useful for inspecting or modifying ISO structures without using higher-level abstractions. ```APIDOC ## IsoFile ### Description Represents the root container of an MP4/ISO file, providing direct read access to every box by type-safe traversal. Useful for inspecting or modifying raw ISO structures. ### Method `new IsoFile(String filePath)` ### Parameters #### Path Parameters - **filePath** (String) - Required - The path to the MP4 file. ### Request Example ```java import org.mp4parser.IsoFile; import org.mp4parser.boxes.iso14496.part12.MovieBox; // Open file and read duration directly from the movie header box IsoFile isoFile = new IsoFile("video.mp4"); MovieBox moov = isoFile.getMovieBox(); double durationSeconds = (double) moov.getMovieHeaderBox().getDuration() / moov.getMovieHeaderBox().getTimescale(); System.out.println("Duration: " + durationSeconds + "s"); // Iterate over all top-level boxes for (var box : isoFile.getBoxes()) { System.out.println(box.getType() + " size=" + box.getSize()); // e.g.: ftyp size=24, moov size=143210, mdat size=48291870 } isoFile.close(); ``` ### Response #### Success Response (IsoFile) - **IsoFile** - An object representing the parsed ISO file structure. #### Response Example ``` Duration: 123.45s ftyp size=24 moov size=143210 mdat size=48291870 ``` ``` -------------------------------- ### Mux H.264 and AAC into MP4 Source: https://context7.com/sannies/mp4parser/llms.txt Wraps raw H.264 (Annex-B or AVCC) and ADTS AAC streams using H264TrackImpl and AACTrackImpl, then combines them into a Movie and builds an MP4 container with DefaultMp4Builder. Requires FileDataSourceImpl for input files. ```java import org.mp4parser.Container; import org.mp4parser.muxer.FileDataSourceImpl; import org.mp4parser.muxer.Movie; import org.mp4parser.muxer.builder.DefaultMp4Builder; import org.mp4parser.muxer.tracks.AACTrackImpl; import org.mp4parser.muxer.tracks.h264.H264TrackImpl; import java.io.FileOutputStream; // Wrap raw elementary streams H264TrackImpl videoTrack = new H264TrackImpl(new FileDataSourceImpl("video.h264")); AACTrackImpl audioTrack = new AACTrackImpl(new FileDataSourceImpl("audio.aac")); // Assemble the movie Movie movie = new Movie(); movie.addTrack(videoTrack); movie.addTrack(audioTrack); // Build and write the MP4 container Container mp4 = new DefaultMp4Builder().build(movie); try (FileOutputStream fos = new FileOutputStream("output.mp4")) { mp4.writeContainer(fos.getChannel()); } // output.mp4 now contains interleaved H.264 video + AAC audio ``` -------------------------------- ### Build MP4 Container Source: https://github.com/sannies/mp4parser/blob/master/README.md Use DefaultMp4Builder to construct the MP4 container from the Movie object. ```java Container mp4file = new DefaultMp4Builder().build(movie); ``` -------------------------------- ### Build Fragmented MP4 (fMP4) with FragmentedMp4Builder Source: https://context7.com/sannies/mp4parser/llms.txt Generates a fragmented MP4 (fMP4) suitable for DASH, HLS CMAF, and smooth-streaming. Each fragment consists of an moof+mdat pair. A custom Fragmenter can be used to control fragment boundaries. ```java import org.mp4parser.Container; import org.mp4parser.muxer.Movie; import org.mp4parser.muxer.builder.FragmentedMp4Builder; import org.mp4parser.muxer.container.mp4.MovieCreator; import java.io.FileOutputStream; Movie movie = MovieCreator.build("source.mp4"); FragmentedMp4Builder builder = new FragmentedMp4Builder(); Container fmp4 = builder.build(movie); try (FileOutputStream fos = new FileOutputStream("output.fmp4")) { fmp4.writeContainer(fos.getChannel()); } ``` -------------------------------- ### Rotate Video with Matrix Source: https://context7.com/sannies/mp4parser/llms.txt Sets the display rotation hint in the mvhd box using pre-built rotation matrices. Use ROTATE_0, ROTATE_90, ROTATE_180, or ROTATE_270. ```java import org.mp4parser.muxer.Movie; import org.mp4parser.muxer.builder.DefaultMp4Builder; import org.mp4parser.muxer.container.mp4.MovieCreator; import org.mp4parser.support.Matrix; import java.io.FileOutputStream; Movie movie = MovieCreator.build("portrait.mp4"); movie.setMatrix(Matrix.ROTATE_90); // or ROTATE_180, ROTATE_270 new DefaultMp4Builder().build(movie) .writeContainer(new FileOutputStream("rotated.mp4").getChannel()); ``` -------------------------------- ### Real-time Fragmented MP4 Writing with Streaming Module Source: https://context7.com/sannies/mp4parser/llms.txt Use this snippet for real-time ingestion pipelines where output can be an HTTP response or broadcast socket. It requires H.264/AAC input files and an ExecutorService for track processing. ```java import org.mp4parser.streaming.input.aac.AdtsAacStreamingTrack; import org.mp4parser.streaming.input.h264.H264AnnexBTrack; import org.mp4parser.streaming.output.mp4.FragmentedMp4Writer; import org.mp4parser.streaming.StreamingTrack; import java.io.FileInputStream; import java.io.FileOutputStream; import java.nio.channels.WritableByteChannel; import java.util.Arrays; import java.util.concurrent.*; H264AnnexBTrack videoTrack = new H264AnnexBTrack(new FileInputStream("video.h264")); AdtsAacStreamingTrack audioTrack = new AdtsAacStreamingTrack( new FileInputStream("audio.aac"), 48000, 128000); WritableByteChannel out = new FileOutputStream("live.fmp4").getChannel(); FragmentedMp4Writer writer = new FragmentedMp4Writer( Arrays.asList(videoTrack, audioTrack), out); ExecutorService es = Executors.newCachedThreadPool(); CompletionService cs = new ExecutorCompletionService<>(es); cs.submit(videoTrack); cs.submit(audioTrack); // Wait for both tracks to finish int completed = 0; while (completed < 2) { cs.take().get(); // throws ExecutionException on error completed++; } writer.close(); // flushes remaining buffered samples es.shutdown(); ``` -------------------------------- ### Trim Track with ClippedTrack Source: https://context7.com/sannies/mp4parser/llms.txt Wraps an existing track to expose only a specified sample range. Ensure cut points are aligned to sync samples before use. ```java import org.mp4parser.Container; import org.mp4parser.muxer.Movie; import org.mp4parser.muxer.Track; import org.mp4parser.muxer.builder.DefaultMp4Builder; import org.mp4parser.muxer.container.mp4.MovieCreator; import org.mp4parser.muxer.tracks.AppendTrack; import org.mp4parser.muxer.tracks.ClippedTrack; import java.io.FileOutputStream; import java.util.Arrays; Movie movie = MovieCreator.build("long_video.mp4"); Movie output = new Movie(); for (Track track : movie.getTracks()) { long[] durations = track.getSampleDurations(); long timescale = track.getTrackMetaData().getTimescale(); // Find sample indices closest to 10s and 20s long startSample = 0, endSample = 0; double currentTime = 0; for (int i = 0; i < durations.length; i++) { if (currentTime <= 10.0) startSample = i; if (currentTime <= 20.0) endSample = i; currentTime += (double) durations[i] / timescale; } // Clip track to the [10s, 20s) window output.addTrack(new ClippedTrack(track, startSample, endSample)); } Container out = new DefaultMp4Builder().build(output); try (FileOutputStream fos = new FileOutputStream("clip.mp4")) { out.writeContainer(fos.getChannel()); } ``` -------------------------------- ### Concatenate Tracks with AppendTrack Source: https://context7.com/sannies/mp4parser/llms.txt Combines multiple tracks of the same type (e.g., video or audio) into a single logical track by sequentially concatenating their samples. Useful for joining multiple recordings. Requires tracks to have identical codec configurations. ```java import org.mp4parser.Container; import org.mp4parser.muxer.Movie; import org.mp4parser.muxer.Track; import org.mp4parser.muxer.builder.DefaultMp4Builder; import org.mp4parser.muxer.container.mp4.MovieCreator; import org.mp4parser.muxer.tracks.AppendTrack; import java.io.FileOutputStream; import java.util.ArrayList; import java.util.List; String[] files = {"part1.mp4", "part2.mp4", "part3.mp4"}; List videoTracks = new ArrayList<>(); List audioTracks = new ArrayList<>(); for (String f : files) { Movie m = MovieCreator.build(f); for (Track t : m.getTracks()) { if ("vide".equals(t.getHandler())) videoTracks.add(t); if ("soun".equals(t.getHandler())) audioTracks.add(t); } } Movie result = new Movie(); result.addTrack(new AppendTrack(videoTracks.toArray(new Track[0]))); result.addTrack(new AppendTrack(audioTracks.toArray(new Track[0]))); Container out = new DefaultMp4Builder().build(result); try (FileOutputStream fos = new FileOutputStream("joined.mp4")) { out.writeContainer(fos.getChannel()); } ``` -------------------------------- ### Write MP4 Container to File Source: https://github.com/sannies/mp4parser/blob/master/README.md Write the generated MP4 container to a file using FileChannel. ```java FileChannel fc = new FileOutputStream(new File("output.mp4")).getChannel(); mp4file.writeContainer(fc); fc.close(); ``` -------------------------------- ### Unmux MP4 into Per-Track Files Source: https://context7.com/sannies/mp4parser/llms.txt Splits a multi-track MP4 file into individual MP4 files, one for each track. Uses DefaultMp4Builder and MovieCreator. ```java import org.mp4parser.muxer.Movie; import org.mp4parser.muxer.Track; import org.mp4parser.muxer.builder.DefaultMp4Builder; import org.mp4parser.muxer.container.mp4.MovieCreator; import java.io.RandomAccessFile; import java.util.Collections; Movie movie = MovieCreator.build("multi_track.mp4"); DefaultMp4Builder builder = new DefaultMp4Builder(); for (Track track : movie.getTracks()) { Movie single = new Movie(Collections.singletonList(track)); String outFile = track.getHandler() + "_track" + track.getTrackMetaData().getTrackId() + ".mp4"; builder.build(single) .writeContainer(new RandomAccessFile(outFile, "rw").getChannel()); System.out.println("Wrote " + outFile); // e.g.: Wrote vide_track1.mp4 / Wrote soun_track2.mp4 } ``` -------------------------------- ### Adding Text Subtitle Tracks to MP4 Movies Source: https://context7.com/sannies/mp4parser/llms.txt This snippet demonstrates how to create and add WebVTT or text subtitles to an existing MP4 movie. Ensure you have a base MP4 file and provide timed text lines. ```java import org.mp4parser.Container; import org.mp4parser.muxer.Movie; import org.mp4parser.muxer.Track; import org.mp4parser.muxer.builder.DefaultMp4Builder; import org.mp4parser.muxer.container.mp4.MovieCreator; import org.mp4parser.muxer.tracks.TextTrackImpl; import java.io.FileOutputStream; import java.util.List; Movie movie = MovieCreator.build("video_no_subs.mp4"); TextTrackImpl textTrack = new TextTrackImpl(); // Add timed text lines: (startMs, endMs, text) textTrack.getSubs().add(new TextTrackImpl.Line(0, 4000, "Hello, World!")); textTrack.getSubs().add(new TextTrackImpl.Line(5000, 9000, "This is a subtitle.")); textTrack.getSubs().add(new TextTrackImpl.Line(10000, 14000, "Goodbye!")); Movie output = new Movie(); for (Track t : movie.getTracks()) { output.addTrack(t); } output.addTrack(textTrack); Container out = new DefaultMp4Builder().build(output); try (FileOutputStream fos = new FileOutputStream("with_subs.mp4")) { out.writeContainer(fos.getChannel()); } ``` -------------------------------- ### Gradle Dependency for MP4 Parser Source: https://context7.com/sannies/mp4parser/llms.txt Add the isoparser and muxer modules to your Gradle project to use the MP4 Parser library. ```gradle compile 'org.mp4parser:isoparser:1.9.27' compile 'org.mp4parser:muxer:1.9.27' ``` -------------------------------- ### Add MP4 Parser Dependency (Gradle) Source: https://github.com/sannies/mp4parser/blob/master/README.md Include this dependency in your Gradle project to use the MP4 Parser library. ```gradle compile 'org.mp4parser:isoparser:1.9.27' ``` -------------------------------- ### Read and Inspect an Existing MP4 File Source: https://context7.com/sannies/mp4parser/llms.txt Use MovieCreator.build to parse an MP4 file and access its tracks and metadata. This method provides a high-level API for interacting with MP4 content. ```java import org.mp4parser.muxer.Movie; import org.mp4parser.muxer.Track; import org.mp4parser.muxer.container.mp4.MovieCreator; // Open and inspect an existing MP4 Movie movie = MovieCreator.build("input.mp4"); for (Track track : movie.getTracks()) { System.out.println("Handler : " + track.getHandler()); // "vide", "soun", "text", ... System.out.println("Samples : " + track.getSamples().size()); System.out.println("Timescale: " + track.getTrackMetaData().getTimescale()); System.out.println("Duration : " + track.getDuration() + " ticks"); } // Output example: // Handler : vide // Samples : 1800 // Timescale: 90000 // Duration : 162000000 ticks ``` -------------------------------- ### Maven Dependency for MP4 Parser Source: https://context7.com/sannies/mp4parser/llms.txt Add the isoparser and muxer modules to your Maven project to use the MP4 Parser library. ```xml org.mp4parser isoparser 1.9.27 org.mp4parser muxer 1.9.27 ``` -------------------------------- ### Read Apple Metadata Title Tag Source: https://context7.com/sannies/mp4parser/llms.txt Reads the '©nam' (title) tag from an MP4 file using IsoFile and Path. Requires the org.mp4parser.boxes.apple package. ```java import org.mp4parser.IsoFile; import org.mp4parser.boxes.apple.AppleNameBox; import org.mp4parser.tools.Path; import java.io.FileInputStream; // READ title tag IsoFile isoFile = new IsoFile(new FileInputStream("video.mp4").getChannel()); AppleNameBox nam = Path.getPath(isoFile, "moov[0]/udta[0]/meta[0]/ilst/©nam"); if (nam != null) { System.out.println("Title: " + nam.getValue()); // Output: Title: My Video Title } isofile.close(); ``` -------------------------------- ### Add MP4 Parser Dependency (Maven) Source: https://github.com/sannies/mp4parser/blob/master/README.md Add this dependency to your Maven project's pom.xml to integrate the MP4 Parser library. ```xml org.mp4parser isoparser 1.9.27 ``` -------------------------------- ### Add Tracks to Movie Object Source: https://github.com/sannies/mp4parser/blob/master/README.md Combine the created H.264 and AAC track objects into a Movie object for further processing. ```java Movie movie = new Movie(); movie.addTrack(h264Track); movie.addTrack(aacTrack); ``` -------------------------------- ### Extract Raw H.264 Elementary Stream Source: https://context7.com/sannies/mp4parser/llms.txt Extracts a raw H.264 elementary stream from an MP4 file. This involves low-level box access, sample iteration, and retrieving SPS/PPS NAL units. ```java import org.mp4parser.IsoFile; import org.mp4parser.boxes.iso14496.part12.TrackBox; import org.mp4parser.boxes.iso14496.part15.AvcConfigurationBox; import org.mp4parser.muxer.FileRandomAccessSourceImpl; import org.mp4parser.muxer.Sample; import org.mp4parser.muxer.container.mp4.Mp4SampleList; import org.mp4parser.tools.IsoTypeReaderVariable; import org.mp4parser.tools.Path; import java.io.FileOutputStream; import java.io.RandomAccessFile; import java.nio.Buffer; import java.nio.ByteBuffer; import java.nio.channels.FileChannel; IsoFile isoFile = new IsoFile("video.mp4"); // Find the H.264 track TrackBox trackBox = null; long trackId = -1; for (TrackBox tb : Path.getPaths(isoFile, "moov/trak/")) { if (Path.getPath(tb, "mdia/minf/stbl/stsd/avc1") != null) { trackBox = tb; trackId = tb.getTrackHeaderBox().getTrackId(); } } AvcConfigurationBox avcC = Path.getPath(trackBox, "mdia/minf/stbl/stsd/avc1/avcC"); int nalLenSize = avcC.getLengthSizeMinusOne() + 1; Mp4SampleList samples = new Mp4SampleList(trackId, isoFile, new FileRandomAccessSourceImpl(new RandomAccessFile("video.mp4", "r"))); ByteBuffer startCode = ByteBuffer.wrap(new byte[]{0, 0, 0, 1}); try (FileChannel fc = new FileOutputStream("output.h264").getChannel()) { // Write SPS fc.write((ByteBuffer) ((Buffer) startCode).rewind()); fc.write(avcC.getSequenceParameterSets().get(0)); // Write PPS fc.write((ByteBuffer) ((Buffer) startCode).rewind()); fc.write(avcC.getPictureParameterSets().get(0)); for (Sample sample : samples) { ByteBuffer bb = sample.asByteBuffer(); while (bb.remaining() > 0) { int len = (int) IsoTypeReaderVariable.read(bb, nalLenSize); fc.write((ByteBuffer) ((Buffer) startCode).rewind()); fc.write((ByteBuffer) ((Buffer) bb.slice()).limit(len)); ((Buffer) bb).position(bb.position() + len); } } } ``` -------------------------------- ### CENC Encryption and Decryption Source: https://context7.com/sannies/mp4parser/llms.txt Encrypts and decrypts track samples using AES-CTR (CENC). Requires a SecretKey and a key-ID UUID. The encrypted track is detectable by MovieCreator. ```java import org.mp4parser.Container; import org.mp4parser.muxer.Movie; import org.mp4parser.muxer.Track; import org.mp4parser.muxer.builder.DefaultMp4Builder; import org.mp4parser.muxer.container.mp4.MovieCreator; import org.mp4parser.muxer.tracks.encryption.CencDecryptingTrackImpl; import org.mp4parser.muxer.tracks.encryption.CencEncryptedTrack; import org.mp4parser.muxer.tracks.encryption.CencEncryptingTrackImpl; import javax.crypto.SecretKey; import javax.crypto.spec.SecretKeySpec; import java.io.ByteArrayOutputStream; import java.io.FileOutputStream; import java.nio.channels.Channels; import java.util.UUID; // 16-byte AES key (use a real key in production) SecretKey key = new SecretKeySpec(new byte[16], "AES"); UUID keyId = UUID.randomUUID(); // --- ENCRYPT --- Movie plain = MovieCreator.build("input.mp4"); Movie encrypted = new Movie(); for (Track t : plain.getTracks()) { encrypted.addTrack(new CencEncryptingTrackImpl(t, keyId, key, /*subsample=*/true)); } ByteArrayOutputStream encBytes = new ByteArrayOutputStream(); new DefaultMp4Builder().build(encrypted).writeContainer(Channels.newChannel(encBytes)); try (FileOutputStream fos = new FileOutputStream("encrypted.mp4")) { fos.write(encBytes.toByteArray()); } // --- DECRYPT --- Movie encMovie = MovieCreator.build("encrypted.mp4"); Movie decrypted = new Movie(); for (Track t : encMovie.getTracks()) { if (t instanceof CencEncryptedTrack) { decrypted.addTrack(new CencDecryptingTrackImpl((CencEncryptedTrack) t, key)); } else { decrypted.addTrack(t); } } new DefaultMp4Builder().build(decrypted) .writeContainer(new FileOutputStream("decrypted.mp4").getChannel()); ``` === COMPLETE CONTENT === This response contains all available snippets from this library. No additional content exists. Do not make further requests.