101 lines
2.6 KiB
Markdown
101 lines
2.6 KiB
Markdown
# MP4 muxer
|
|
|
|
## Info
|
|
|
|
This code is only meant to work with ALAC and EAC3 (JOC) streams, for any other codecs you're on your own.
|
|
Use at your own risk. If you use this to create files and don't validate them afterwards, don't blame me if something goes wrong.
|
|
|
|
None of this code will parse MP4 files for you. If your source file is a different MP4 file (or a different format entirely),
|
|
you will have to figure out how to parse the required information (see `Usage`) yourself.
|
|
|
|
For more information, see [here](https://z8.re/blog/mp4).
|
|
|
|
|
|
## Usage
|
|
|
|
You will need to provide the following info:
|
|
- Sample rate
|
|
- Bit depth
|
|
- mdat box as a bytearray
|
|
- Sizes for all samples contained within the mdat box
|
|
- Total duration
|
|
- (optional: Tags)
|
|
|
|
Writing tags is optional, even without them the file will play back just fine. They're written to `moov/udta/meta/ilst`.
|
|
|
|
If you do not create a `Tags` object and/or do not use `set_tags()`, then the `udta` box will not be created.
|
|
|
|
Note for EAC3 JOC: This code assumes that there is only a single independed substream present and that the
|
|
values in the EAC3 specific box within `stsd` of the source file match the following (I left out the reserved bits here):
|
|
```python
|
|
fscod = 0
|
|
bsid = 16
|
|
asvc = 0
|
|
bsmod = 0
|
|
acmod = 7
|
|
lfeon = 1
|
|
num_dep_sub = 0
|
|
ec3_job_flag = 1
|
|
joc_complexity_index = 16
|
|
```
|
|
|
|
## Example
|
|
|
|
```python
|
|
from mp4muxer_alac import MP4MuxerALAC
|
|
|
|
m = MP4MuxerALAC()
|
|
m.set_sample_rate(44100)
|
|
m.set_bit_depth(16)
|
|
sample_sizes = [7424, 6915, 6830, 6737, ..., 2700, 1443]
|
|
m.set_sample_sizes(sample_sizes)
|
|
m.set_total_duration(10442880)
|
|
with open("m.dat", "rb") as f:
|
|
mdat = bytearray(f.read())
|
|
m.set_mdat_data(mdat)
|
|
|
|
t = Tags()
|
|
t.track_name = "Insert Interesting Title Here"
|
|
t.artist = "Artist X & Y"
|
|
t.album_artist = "Artist X"
|
|
t.composer = "X, Y, Z"
|
|
t.album_name = "First Track - Single"
|
|
t.genre = "Dubstep;Country"
|
|
t.track_number = 1
|
|
t.total_number_of_tracks = 1
|
|
t.disc_number = 1
|
|
t.total_number_of_discs = 1
|
|
t.date = "2020-05-22"
|
|
t.upc = "5556667778889"
|
|
t.label = "We Sell Records Rec."
|
|
with open("cover.jpg", "rb") as f:
|
|
t.cover_data = bytearray(f.read())
|
|
t.cover_format = "jpeg"
|
|
t.isrc = "CYZXL20044078"
|
|
t.copyright = "℗ 2021 We Sell Records Rec."
|
|
t.apple_store_catalog_id = 9999998
|
|
t.album_title_id = 9999999
|
|
t.playlist_id = 32423444
|
|
|
|
m.set_tags(t)
|
|
m.create()
|
|
m.out("A Piece of Music.m4a")
|
|
```
|
|
|
|
For EAC3 JOC the process is similar:
|
|
|
|
```python
|
|
from mp4muxer_eac3 import MP4MuxerEAC3
|
|
|
|
m = MP4MuxerEAC3()
|
|
m.set_sample_rate(sr)
|
|
m.set_bit_depth(bd)
|
|
m.set_bit_rate(768)
|
|
m.set_sample_sizes(sample_sizes)
|
|
m.set_timestamp(timestamp)
|
|
m.set_mdat_data(mdat)
|
|
|
|
...
|
|
|
|
```
|