From 793cb6023d537ae025986d799ec5bbf2c147998e Mon Sep 17 00:00:00 2001 From: Billal GHILAS Date: Tue, 6 Oct 2026 09:46:08 +0100 Subject: [PATCH 1/3] feat: add support for uuid box --- lib/ex_mp4/box/moov.ex | 16 +++++++++++----- lib/ex_mp4/box/trun.ex | 2 +- lib/ex_mp4/box/uuid.ex | 24 ++++++++++++++++++++++-- lib/ex_mp4/fwriter.ex | 10 +++++++--- lib/ex_mp4/reader.ex | 6 +++++- lib/ex_mp4/writer.ex | 14 +++++++++++--- test/ex_mp4/box_test.exs | 28 ++++++++++++++++++++++++++++ test/ex_mp4/fwriter_test.exs | 27 +++++++++++++++++++++++++++ test/ex_mp4/writer_test.exs | 28 ++++++++++++++++++++++++++++ 9 files changed, 140 insertions(+), 15 deletions(-) diff --git a/lib/ex_mp4/box/moov.ex b/lib/ex_mp4/box/moov.ex index 1b1af27..1615ce4 100644 --- a/lib/ex_mp4/box/moov.ex +++ b/lib/ex_mp4/box/moov.ex @@ -5,20 +5,21 @@ defmodule ExMP4.Box.Moov do import ExMP4.Box.Utils, only: [parse_header: 1] - alias ExMP4.Box.{Mvex, Mvhd, Trak} + alias ExMP4.Box.{Mvex, Mvhd, Trak, UUID} @type t :: %__MODULE__{ mvhd: Mvhd.t(), trak: [Trak.t()], - mvex: Mvex.t() | nil + mvex: Mvex.t() | nil, + uuid: [UUID.t()] } - defstruct mvhd: %Mvhd{}, trak: [], mvex: nil + defstruct mvhd: %Mvhd{}, trak: [], mvex: nil, uuid: [] defimpl ExMP4.Box do def size(box) do ExMP4.header_size() + ExMP4.Box.size(box.mvhd) + ExMP4.Box.size(box.trak) + - ExMP4.Box.size(box.mvex) + ExMP4.Box.size(box.mvex) + ExMP4.Box.size(box.uuid) end def parse(box, data), do: do_parse(box, data) @@ -28,7 +29,8 @@ defmodule ExMP4.Box.Moov do <>, ExMP4.Box.serialize(box.mvhd), ExMP4.Box.serialize(box.trak), - ExMP4.Box.serialize(box.mvex) + ExMP4.Box.serialize(box.mvex), + ExMP4.Box.serialize(box.uuid) ] end @@ -49,6 +51,10 @@ defmodule ExMP4.Box.Moov do box = %{box | mvex: ExMP4.Box.parse(%Mvex{}, box_data)} {box, rest} + {"uuid", box_data, rest} -> + box = %{box | uuid: box.uuid ++ [ExMP4.Box.parse(%UUID{}, box_data)]} + {box, rest} + {_box_name, _box_data, rest} -> # box = %{box | mdia: ExMP4.Box.parse(%Mdia{}, box_data)} {box, rest} diff --git a/lib/ex_mp4/box/trun.ex b/lib/ex_mp4/box/trun.ex index 5e1858c..40ec7b5 100644 --- a/lib/ex_mp4/box/trun.ex +++ b/lib/ex_mp4/box/trun.ex @@ -46,7 +46,7 @@ defmodule ExMP4.Box.Trun do {first_sample_flags, rest} = parse_entry(flags &&& 0x4, rest) {entries, <<>>} = - Enum.reduce(1..sample_count, {[], rest}, fn _idx, {entries, data} -> + Enum.reduce(1..sample_count//1, {[], rest}, fn _idx, {entries, data} -> {sample_duration, rest} = parse_entry(flags &&& 0x100, data) {sample_size, rest} = parse_entry(flags &&& 0x200, rest) {sample_flags, rest} = parse_entry(flags &&& 0x400, rest) diff --git a/lib/ex_mp4/box/uuid.ex b/lib/ex_mp4/box/uuid.ex index f823000..fd9548f 100644 --- a/lib/ex_mp4/box/uuid.ex +++ b/lib/ex_mp4/box/uuid.ex @@ -1,14 +1,34 @@ defmodule ExMP4.Box.UUID do @moduledoc """ Module describing a UUID box. + + A `uuid` box is a user extension box, the following fields are available: + * `type` - The 16 bytes extended type (`usertype`) identifying the box. + * `data` - The raw payload of the box. """ @type t :: %__MODULE__{ - type: binary(), + type: <<_::128>>, data: binary() } - defstruct [:type, :data] + defstruct type: nil, data: <<>> + + @doc """ + Create a new UUID box. + + `type` must be a 16 bytes binary. + """ + @spec new(<<_::128>>, binary()) :: t() + def new(type, data \\ <<>>) + + def new(<<_::binary-size(16)>> = type, data) when is_binary(data) do + %__MODULE__{type: type, data: data} + end + + def new(type, _data) do + raise ArgumentError, "uuid type must be a 16 bytes binary, got: #{inspect(type)}" + end defimpl ExMP4.Box do def size(box) do diff --git a/lib/ex_mp4/fwriter.ex b/lib/ex_mp4/fwriter.ex index f996548..f85c14f 100644 --- a/lib/ex_mp4/fwriter.ex +++ b/lib/ex_mp4/fwriter.ex @@ -30,7 +30,8 @@ defmodule ExMP4.FWriter do creation_time: DateTime.t(), modification_time: DateTime.t(), duration: integer() | boolean(), - moof_base_offset: boolean() + moof_base_offset: boolean(), + uuid: [Box.UUID.t()] ] @type writer_options :: any() @@ -67,6 +68,7 @@ defmodule ExMP4.FWriter do If an integer, it's the total duration in the `movie` timescale and it'll be set in the `mehd` box. * `moof_base_offset` - if `true`, it indicates that the `base‐data‐offset` for the track fragments is the position of the first byte of the enclosing Movie Fragment Box. Defaults to: `false`. + * `uuid` - A list of `ExMP4.Box.UUID` boxes to include in the `moov` box. Defaults to: `[]`. The last argument is an optional module implementing `ExMP4.FragDataWriter`. """ @@ -260,7 +262,8 @@ defmodule ExMP4.FWriter do modification_time: utc_date, duration: false, moof_base_offset: false, - sidx: false + sidx: false, + uuid: [] ) end @@ -289,7 +292,8 @@ defmodule ExMP4.FWriter do mvex: %Box.Mvex{ mehd: mehd_box, trex: Enum.map(tracks, & &1.trex) - } + }, + uuid: opts[:uuid] } writer_state = writer.writer_mod.write_init_header(writer.writer_state, [ftyp_box, movie_box]) diff --git a/lib/ex_mp4/reader.ex b/lib/ex_mp4/reader.ex index 86db1b2..bf7b817 100644 --- a/lib/ex_mp4/reader.ex +++ b/lib/ex_mp4/reader.ex @@ -13,6 +13,7 @@ defmodule ExMP4.Reader do * `major_brand` * `minor_version` * `compatible_brands` + * `uuid` - List of `uuid` boxes (`ExMP4.Box.UUID`) found in the `moov` box. ## Examples @@ -73,6 +74,7 @@ defmodule ExMP4.Reader do progressive?: boolean(), creation_time: DateTime.t(), modification_time: DateTime.t(), + uuid: [Box.UUID.t()], # private fields reader_mod: module(), @@ -94,6 +96,7 @@ defmodule ExMP4.Reader do :reader_mod, :reader_state, :tracks, + uuid: [], location: 0 ] @@ -280,7 +283,8 @@ defmodule ExMP4.Reader do modification_time: moov.mvhd.modification_time, fragmented?: not is_nil(moov.mvex), progressive?: is_nil(reader.progressive?), - tracks: tracks + tracks: tracks, + uuid: moov.uuid } end diff --git a/lib/ex_mp4/writer.ex b/lib/ex_mp4/writer.ex index 6808eec..7816a12 100644 --- a/lib/ex_mp4/writer.ex +++ b/lib/ex_mp4/writer.ex @@ -186,16 +186,23 @@ defmodule ExMP4.Writer do @doc """ Write the trailer and close the stream. + + The following options can be provided: + * `creation_time` - Set the creation time. Defaults to: now. + * `modification_time` - Set the modification time. Defaults to: now. + * `uuid` - A list of `ExMP4.Box.UUID` boxes to include in the `moov` box. Defaults to: `[]`. """ @spec write_trailer(t()) :: :ok def write_trailer(%{fast_start: fast_start} = writer, opts \\ []) do [ creation_time: creation_time, - modification_time: modification_time + modification_time: modification_time, + uuid: uuid ] = Keyword.validate!(opts, creation_time: DateTime.utc_now(:second), - modification_time: DateTime.utc_now(:second) + modification_time: DateTime.utc_now(:second), + uuid: [] ) |> Enum.sort() @@ -218,7 +225,8 @@ defmodule ExMP4.Writer do creation_time: creation_time, modification_time: modification_time }, - trak: trak + trak: trak, + uuid: uuid } after_ftyp = {:bof, writer.ftyp_size} diff --git a/test/ex_mp4/box_test.exs b/test/ex_mp4/box_test.exs index 9243086..7ede606 100644 --- a/test/ex_mp4/box_test.exs +++ b/test/ex_mp4/box_test.exs @@ -148,4 +148,32 @@ defmodule ExMP4.BoxTest do assert Box.serialize(styp) |> IO.iodata_to_binary() == expected assert Box.parse(%Box.Styp{}, :binary.part(expected, 8, 16)) == styp end + + test "serialize and parse uuid" do + type = <<0::128>> + uuid = Box.UUID.new(type, "some data") + + expected = <<33::32, "uuid", type::binary, "some data">> + + assert Box.size(uuid) == 33 + assert Box.serialize(uuid) |> IO.iodata_to_binary() == expected + assert Box.parse(%Box.UUID{}, :binary.part(expected, 8, 25)) == uuid + end + + test "uuid type must be 16 bytes" do + assert_raise ArgumentError, fn -> Box.UUID.new("short", "data") end + end + + test "parse and serialize moov with uuid boxes" do + assert {:ok, <<_size::32, "moov", rest::binary>>} = File.read("test/fixtures/moov.bin") + + moov = Box.parse(%Box.Moov{}, rest) + uuids = [Box.UUID.new(<<1::128>>, "first"), Box.UUID.new(<<2::128>>, "second")] + moov = %{moov | uuid: uuids} + + data = Box.serialize(moov) |> IO.iodata_to_binary() + assert <> = data + assert size == Box.size(moov) + assert Box.parse(%Box.Moov{}, rest) == moov + end end diff --git a/test/ex_mp4/fwriter_test.exs b/test/ex_mp4/fwriter_test.exs index 7c58867..d22d0c1 100644 --- a/test/ex_mp4/fwriter_test.exs +++ b/test/ex_mp4/fwriter_test.exs @@ -72,6 +72,33 @@ defmodule ExMP4.FWriterTest do assert :ok = ExMP4.Reader.close(reader) end + test "write fragmented mp4 with uuid boxes", %{tmp_dir: tmp_dir} do + filepath = Path.join(tmp_dir, "out.mp4") + uuids = [ExMP4.Box.UUID.new(<<1::128>>, "data")] + + assert {:ok, writer} = + FWriter.new(filepath, [video_track(), audio_track()], uuid: uuids, duration: true) + + video_samples = for idx <- 0..4, do: video_sample(idx) + + assert :ok = + writer + |> FWriter.create_fragment() + |> then(&Enum.reduce(video_samples, &1, fn s, w -> FWriter.write_sample(w, s) end)) + |> FWriter.flush_fragment() + |> FWriter.close() + + assert {:ok, reader} = ExMP4.Reader.new(filepath) + assert reader.uuid == uuids + assert reader.duration == 3500 + + for idx <- 0..4 do + assert Enum.at(video_samples, idx) == ExMP4.Reader.read_sample(reader, 1, idx) + end + + assert :ok = ExMP4.Reader.close(reader) + end + test "write fragmented mp4 (base is moof)", %{tmp_dir: tmp_dir} do filepath = Path.join(tmp_dir, "out.mp4") diff --git a/test/ex_mp4/writer_test.exs b/test/ex_mp4/writer_test.exs index 723f7a1..2df16ab 100644 --- a/test/ex_mp4/writer_test.exs +++ b/test/ex_mp4/writer_test.exs @@ -97,6 +97,34 @@ defmodule ExMP4.WriterTest do assert <<_ftyp::binary-size(32), _moov_size::binary-size(4), "moov", _rest::binary>> = data end + for fast_start <- [false, true] do + test "write mp4 with uuid boxes (fast_start: #{fast_start})", %{tmp_dir: tmp_dir} do + filepath = Path.join(tmp_dir, "out.mp4") + uuids = [ExMP4.Box.UUID.new(<<1::128>>, "data"), ExMP4.Box.UUID.new(<<2::128>>)] + + assert :ok = + filepath + |> Writer.new!(fast_start: unquote(fast_start)) + |> Writer.write_header() + |> Writer.add_tracks([video_track(), audio_track()]) + |> then(&Enum.into(Enum.concat(video_samples(), audio_samples()), &1)) + |> Writer.write_trailer(uuid: uuids) + + assert {:ok, reader} = ExMP4.Reader.new(filepath) + assert reader.uuid == uuids + + for {sample, idx} <- Enum.with_index(video_samples()) do + assert sample == ExMP4.Reader.read_sample(reader, 1, idx) + end + + for {sample, idx} <- Enum.with_index(audio_samples()) do + assert sample == ExMP4.Reader.read_sample(reader, 2, idx) + end + + assert :ok = ExMP4.Reader.close(reader) + end + end + defp video_samples do [ {0, 2000, 1000, true}, From de993c549c614001ab1e6989e7b39aed4ebccccb Mon Sep 17 00:00:00 2001 From: Billal GHILAS Date: Tue, 6 Oct 2026 09:47:13 +0100 Subject: [PATCH 2/3] upgrade deps --- mix.lock | 22 +++++++++++----------- 1 file changed, 11 insertions(+), 11 deletions(-) diff --git a/mix.lock b/mix.lock index c3e470d..7866f7a 100644 --- a/mix.lock +++ b/mix.lock @@ -1,19 +1,19 @@ %{ - "benchee": {:hex, :benchee, "1.5.0", "4d812c31d54b0ec0167e91278e7de3f596324a78a096fd3d0bea68bb0c513b10", [:mix], [{:deep_merge, "~> 1.0", [hex: :deep_merge, repo: "hexpm", optional: false]}, {:statistex, "~> 1.1", [hex: :statistex, repo: "hexpm", optional: false]}, {:table, "~> 0.1.0", [hex: :table, repo: "hexpm", optional: true]}], "hexpm", "5b075393aea81b8ae74eadd1c28b1d87e8a63696c649d8293db7c4df3eb67535"}, + "benchee": {:hex, :benchee, "1.5.1", "b95cbc36c4b98969a5c592a246e171041eb683c56bad1cb4f49a3b081ba66087", [:mix], [{:deep_merge, "~> 1.0", [hex: :deep_merge, repo: "hexpm", optional: false]}, {:statistex, "~> 1.1", [hex: :statistex, repo: "hexpm", optional: false]}, {:table, "~> 0.1.0", [hex: :table, repo: "hexpm", optional: true]}], "hexpm", "a539301f8dfd4efc5c5123bfb9d47ebde20092a863a5b5b16c2a60d2243dfce7"}, "bunt": {:hex, :bunt, "1.0.0", "081c2c665f086849e6d57900292b3a161727ab40431219529f13c4ddcf3e7a44", [:mix], [], "hexpm", "dc5f86aa08a5f6fa6b8096f0735c4e76d54ae5c9fa2c143e5a1fc7c1cd9bb6b5"}, - "credo": {:hex, :credo, "1.7.13", "126a0697df6b7b71cd18c81bc92335297839a806b6f62b61d417500d1070ff4e", [:mix], [{:bunt, "~> 0.2.1 or ~> 1.0", [hex: :bunt, repo: "hexpm", optional: false]}, {:file_system, "~> 0.2 or ~> 1.0", [hex: :file_system, repo: "hexpm", optional: false]}, {:jason, "~> 1.0", [hex: :jason, repo: "hexpm", optional: false]}], "hexpm", "47641e6d2bbff1e241e87695b29f617f1a8f912adea34296fb10ecc3d7e9e84f"}, - "deep_merge": {:hex, :deep_merge, "1.0.0", "b4aa1a0d1acac393bdf38b2291af38cb1d4a52806cf7a4906f718e1feb5ee961", [:mix], [], "hexpm", "ce708e5f094b9cd4e8f2be4f00d2f4250c4095be93f8cd6d018c753894885430"}, - "dialyxir": {:hex, :dialyxir, "1.4.6", "7cca478334bf8307e968664343cbdb432ee95b4b68a9cba95bdabb0ad5bdfd9a", [:mix], [{:erlex, ">= 0.2.7", [hex: :erlex, repo: "hexpm", optional: false]}], "hexpm", "8cf5615c5cd4c2da6c501faae642839c8405b49f8aa057ad4ae401cb808ef64d"}, - "earmark_parser": {:hex, :earmark_parser, "1.4.44", "f20830dd6b5c77afe2b063777ddbbff09f9759396500cdbe7523efd58d7a339c", [:mix], [], "hexpm", "4778ac752b4701a5599215f7030989c989ffdc4f6df457c5f36938cc2d2a2750"}, - "erlex": {:hex, :erlex, "0.2.7", "810e8725f96ab74d17aac676e748627a07bc87eb950d2b83acd29dc047a30595", [:mix], [], "hexpm", "3ed95f79d1a844c3f6bf0cea61e0d5612a42ce56da9c03f01df538685365efb0"}, - "ex_doc": {:hex, :ex_doc, "0.39.1", "e19d356a1ba1e8f8cfc79ce1c3f83884b6abfcb79329d435d4bbb3e97ccc286e", [:mix], [{:earmark_parser, "~> 1.4.44", [hex: :earmark_parser, repo: "hexpm", optional: false]}, {:makeup_c, ">= 0.1.0", [hex: :makeup_c, repo: "hexpm", optional: true]}, {:makeup_elixir, "~> 0.14 or ~> 1.0", [hex: :makeup_elixir, repo: "hexpm", optional: false]}, {:makeup_erlang, "~> 0.1 or ~> 1.0", [hex: :makeup_erlang, repo: "hexpm", optional: false]}, {:makeup_html, ">= 0.1.0", [hex: :makeup_html, repo: "hexpm", optional: true]}], "hexpm", "8abf0ed3e3ca87c0847dfc4168ceab5bedfe881692f1b7c45f4a11b232806865"}, + "credo": {:hex, :credo, "1.7.19", "cc52129665fc7c15143d47838fda0f9cd6dac9ceced7bf4da6f85fcbfe64b12a", [:mix], [{:bunt, "~> 0.2.1 or ~> 1.0", [hex: :bunt, repo: "hexpm", optional: false]}, {:file_system, "~> 0.2 or ~> 1.0", [hex: :file_system, repo: "hexpm", optional: false]}, {:jason, "~> 1.0", [hex: :jason, repo: "hexpm", optional: false]}], "hexpm", "2d8bc95d5a7bb99dd2613621d4f08c6a3575c3fd4b62e6a2b48a100352a557b8"}, + "deep_merge": {:hex, :deep_merge, "1.0.2", "476aa7ea61c54de96220051b998d893869069094da65b96101aebf79416f8a1e", [:mix], [], "hexpm", "737a53cdc9758fedbb608bdc213969e65729466c4ef3cd8e8726d0335dff116c"}, + "dialyxir": {:hex, :dialyxir, "1.4.8", "7ef671a8aff9948b091d8c30f09467fbb16e77305cda451bce48109a0f5e021c", [:mix], [{:erlex, ">= 0.2.8", [hex: :erlex, repo: "hexpm", optional: false]}], "hexpm", "cbd5a851571e5dfeb32aaf2e840bfa98b7864cb3071bf2ef5d95d1276b12e072"}, + "earmark_parser": {:hex, :earmark_parser, "1.4.46", "67607a0532e810c6f630a515c548d0b24949643f168cc556303bee4cf96105c7", [:mix], [], "hexpm", "9c44636e8a1c68c62f526b2dcd85d941dbbcee7ab82cf64ba06ce28bef8e89f5"}, + "erlex": {:hex, :erlex, "0.2.9", "7debbbaa9f4f368b8cd648983e0f1d7963028508e9c59e9d4ed504e94ef52a55", [:mix], [], "hexpm", "8cfffc0ec7159e6d73de2ab28a588064de80f88b2798d5cbe4482cbbc200178b"}, + "ex_doc": {:hex, :ex_doc, "0.40.4", "66f2e42bf588594d5a8aab31cad87f2ddad09d0da1b1a2f379340ec2c2e497cb", [:mix], [{:earmark_parser, "~> 1.4.46", [hex: :earmark_parser, repo: "hexpm", optional: false]}, {:makeup_c, ">= 0.1.0", [hex: :makeup_c, repo: "hexpm", optional: true]}, {:makeup_elixir, "~> 0.14 or ~> 1.0", [hex: :makeup_elixir, repo: "hexpm", optional: false]}, {:makeup_erlang, "~> 0.1 or ~> 1.0", [hex: :makeup_erlang, repo: "hexpm", optional: false]}, {:makeup_html, ">= 0.1.0", [hex: :makeup_html, repo: "hexpm", optional: true]}], "hexpm", "6222b9e423d76584ee34df2c82a5ed72c2d53dc153f7f483ad28b378694186cc"}, "file_system": {:hex, :file_system, "1.1.1", "31864f4685b0148f25bd3fbef2b1228457c0c89024ad67f7a81a3ffbc0bbad3a", [:mix], [], "hexpm", "7a15ff97dfe526aeefb090a7a9d3d03aa907e100e262a0f8f7746b78f8f87a5d"}, - "jason": {:hex, :jason, "1.4.4", "b9226785a9aa77b6857ca22832cffa5d5011a667207eb2a0ad56adb5db443b8a", [:mix], [{:decimal, "~> 1.0 or ~> 2.0", [hex: :decimal, repo: "hexpm", optional: true]}], "hexpm", "c5eb0cab91f094599f94d55bc63409236a8ec69a21a67814529e8d5f6cc90b3b"}, - "makeup": {:hex, :makeup, "1.2.1", "e90ac1c65589ef354378def3ba19d401e739ee7ee06fb47f94c687016e3713d1", [:mix], [{:nimble_parsec, "~> 1.4", [hex: :nimble_parsec, repo: "hexpm", optional: false]}], "hexpm", "d36484867b0bae0fea568d10131197a4c2e47056a6fbe84922bf6ba71c8d17ce"}, + "jason": {:hex, :jason, "1.4.5", "2e3a008590b0b8d7388c20293e9dcc9cf3e5d642fd2a114e4cbbb52e595d940a", [:mix], [{:decimal, "~> 1.0 or ~> 2.0 or ~> 3.0", [hex: :decimal, repo: "hexpm", optional: true]}], "hexpm", "b0c823996102bcd0239b3c2444eb00409b72f6a140c1950bc8b457d836b30684"}, + "makeup": {:hex, :makeup, "1.2.3", "c3ef0ff83acf305384acba0f70bff87d8732502baa1eb3eb081d8c154fbe18f5", [:mix], [{:nimble_parsec, "~> 1.4", [hex: :nimble_parsec, repo: "hexpm", optional: false]}], "hexpm", "15970751b7021c2bcd7ed56a54b3def23affd3969fb7c214dffdf28e97ce6f76"}, "makeup_elixir": {:hex, :makeup_elixir, "1.0.1", "e928a4f984e795e41e3abd27bfc09f51db16ab8ba1aebdba2b3a575437efafc2", [:mix], [{:makeup, "~> 1.0", [hex: :makeup, repo: "hexpm", optional: false]}, {:nimble_parsec, "~> 1.2.3 or ~> 1.3", [hex: :nimble_parsec, repo: "hexpm", optional: false]}], "hexpm", "7284900d412a3e5cfd97fdaed4f5ed389b8f2b4cb49efc0eb3bd10e2febf9507"}, - "makeup_erlang": {:hex, :makeup_erlang, "1.0.2", "03e1804074b3aa64d5fad7aa64601ed0fb395337b982d9bcf04029d68d51b6a7", [:mix], [{:makeup, "~> 1.0", [hex: :makeup, repo: "hexpm", optional: false]}], "hexpm", "af33ff7ef368d5893e4a267933e7744e46ce3cf1f61e2dccf53a111ed3aa3727"}, + "makeup_erlang": {:hex, :makeup_erlang, "1.1.0", "835f7e60792e08824cda445639555d7bf1bbbddb1b60b306e33cb6f6db24dc74", [:mix], [{:makeup, "~> 1.0", [hex: :makeup, repo: "hexpm", optional: false]}], "hexpm", "1cd6780fb1dd1a03979abaed0fe82712b0625118fd5257d3ebbf73f960c73c3c"}, "media_codecs": {:hex, :media_codecs, "0.10.0", "dcc64779c3b287202fd8083fe49bf11b37f7b6bbd8edf3a9bd756370ee4417c5", [:mix], [], "hexpm", "8ea233ae378acfae3ab95a90f6f5c99711d55f15d0c5fac244d46b42f6a9ca04"}, "nimble_parsec": {:hex, :nimble_parsec, "1.4.2", "8efba0122db06df95bfaa78f791344a89352ba04baedd3849593bfce4d0dc1c6", [:mix], [], "hexpm", "4b21398942dda052b403bbe1da991ccd03a053668d147d53fb8c4e0efe09c973"}, - "statistex": {:hex, :statistex, "1.1.0", "7fec1eb2f580a0d2c1a05ed27396a084ab064a40cfc84246dbfb0c72a5c761e5", [:mix], [], "hexpm", "f5950ea26ad43246ba2cce54324ac394a4e7408fdcf98b8e230f503a0cba9cf5"}, + "statistex": {:hex, :statistex, "1.1.1", "73612aa7f79e53c30569be065fd121e380f1cf57bc4c2da5b41be9246da18df9", [:mix], [], "hexpm", "310c4b49b34adf683de3103639006bed233ab54c08a4add65a531448e653857c"}, "table_rex": {:hex, :table_rex, "4.1.0", "fbaa8b1ce154c9772012bf445bfb86b587430fb96f3b12022d3f35ee4a68c918", [:mix], [], "hexpm", "95932701df195d43bc2d1c6531178fc8338aa8f38c80f098504d529c43bc2601"}, } From 39e988ba4fe050caa7e8484c055c3e094d7e1317 Mon Sep 17 00:00:00 2001 From: Billal GHILAS Date: Tue, 6 Oct 2026 09:50:57 +0100 Subject: [PATCH 3/3] make credo happy --- test/ex_mp4/fwriter_test.exs | 4 ++-- test/ex_mp4/writer_test.exs | 4 ++-- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/test/ex_mp4/fwriter_test.exs b/test/ex_mp4/fwriter_test.exs index d22d0c1..6b5d77c 100644 --- a/test/ex_mp4/fwriter_test.exs +++ b/test/ex_mp4/fwriter_test.exs @@ -5,7 +5,7 @@ defmodule ExMP4.FWriterTest do import ExMP4.Support.Utils - alias ExMP4.{FWriter, Sample} + alias ExMP4.{Box, FWriter, Sample} @moduletag :tmp_dir @@ -74,7 +74,7 @@ defmodule ExMP4.FWriterTest do test "write fragmented mp4 with uuid boxes", %{tmp_dir: tmp_dir} do filepath = Path.join(tmp_dir, "out.mp4") - uuids = [ExMP4.Box.UUID.new(<<1::128>>, "data")] + uuids = [Box.UUID.new(<<1::128>>, "data")] assert {:ok, writer} = FWriter.new(filepath, [video_track(), audio_track()], uuid: uuids, duration: true) diff --git a/test/ex_mp4/writer_test.exs b/test/ex_mp4/writer_test.exs index 2df16ab..b71c96d 100644 --- a/test/ex_mp4/writer_test.exs +++ b/test/ex_mp4/writer_test.exs @@ -5,7 +5,7 @@ defmodule ExMP4.WriterTest do import ExMP4.Support.Utils - alias ExMP4.{Sample, Writer} + alias ExMP4.{Box, Sample, Writer} @moduletag :tmp_dir @@ -100,7 +100,7 @@ defmodule ExMP4.WriterTest do for fast_start <- [false, true] do test "write mp4 with uuid boxes (fast_start: #{fast_start})", %{tmp_dir: tmp_dir} do filepath = Path.join(tmp_dir, "out.mp4") - uuids = [ExMP4.Box.UUID.new(<<1::128>>, "data"), ExMP4.Box.UUID.new(<<2::128>>)] + uuids = [Box.UUID.new(<<1::128>>, "data"), Box.UUID.new(<<2::128>>)] assert :ok = filepath