diff --git a/README.md b/README.md index 7341556c..3553ae0d 100644 --- a/README.md +++ b/README.md @@ -85,7 +85,7 @@ For the full list of input and output options, see [`Boombox.run/2`](https://hex To use Boombox as an Elixir library, add ```elixir -{:boombox, "~> 0.2.4"} +{:boombox, "~> 0.2.5"} ``` to your dependencies or `Mix.install`. diff --git a/lib/boombox.ex b/lib/boombox.ex index 09d0b68b..ed4607e5 100644 --- a/lib/boombox.ex +++ b/lib/boombox.ex @@ -91,11 +91,8 @@ defmodule Boombox do @type input :: (path_or_uri :: String.t()) | {path_or_uri :: String.t(), - [ - hls_variant_selection_policy_opt() - | hls_mode_opt() - | {:framerate, Membrane.H264.framerate() | Membrane.H265.framerate_t()} - ]} + [hls_variant_selection_policy_opt() | hls_mode_opt()] + | [{:framerate, Membrane.H264.framerate() | Membrane.H265.framerate_t()}]} | {:mp4 | :aac | :wav | :mp3 | :ivf | :ogg | :h264 | :h265, location :: String.t()} | {:mp4 | :aac | :wav | :mp3 | :ivf | :ogg, location :: String.t(), transport: :file | :http} @@ -109,11 +106,7 @@ defmodule Boombox do | {:rtsp, url :: String.t()} | {:rtp, in_rtp_opts()} | {:hls, url :: String.t()} - | {:hls, url :: String.t(), - [ - hls_mode_opt() - | hls_variant_selection_policy_opt() - ]} + | {:hls, url :: String.t(), [hls_variant_selection_policy_opt() | hls_mode_opt()]} | {:srt, url :: String.t()} | {:srt, url :: String.t(), srt_auth_opts()} | {:srt, server_awaiting_accept :: ExLibSRT.Server.t()} diff --git a/lib/boombox/internal_bin.ex b/lib/boombox/internal_bin.ex index 129cf3fa..8e2f84d5 100644 --- a/lib/boombox/internal_bin.ex +++ b/lib/boombox/internal_bin.ex @@ -744,7 +744,7 @@ defmodule Boombox.InternalBin do {"rtsp", _ext, :input} -> {:rtsp, value} - {scheme, ".m3u8", :input} when scheme in ["http", "https"] -> + {scheme, ".m3u8", :input} when scheme in [nil, "http", "https"] -> {:hls, value, opts} {nil, ".m3u8", :output} -> @@ -928,9 +928,6 @@ defmodule Boombox.InternalBin do {:stream, opts} -> Keyword.get(opts, :is_live, false) - {:hls, _location, opts} -> - Keyword.get(opts, :mode) == :live - _other -> false end diff --git a/lib/boombox/internal_bin/hls.ex b/lib/boombox/internal_bin/hls.ex index b6713854..e2949de3 100644 --- a/lib/boombox/internal_bin/hls.ex +++ b/lib/boombox/internal_bin/hls.ex @@ -2,13 +2,22 @@ defmodule Boombox.InternalBin.HLS do @moduledoc false import Membrane.ChildrenSpec - + require Logger require Membrane.Pad, as: Pad alias Boombox.InternalBin.{Ready, Wait} alias Membrane.{AAC, H264, HTTPAdaptiveStream, RemoteStream, Time, Transcoder} @spec create_input(String.t(), [Boombox.hls_variant_selection_policy_opt()]) :: Wait.t() def create_input(url, opts) do + maybe_hls_mode = Keyword.get(opts, :mode, nil) + + if maybe_hls_mode != nil do + Logger.warning(""" + Option :mode is deprecated for HLS input. Its value will be ignored. + It was set to #{inspect(maybe_hls_mode)}. + """) + end + variant_selection_policy = Keyword.get(opts, :variant_selection_policy, :highest_resolution) spec = diff --git a/mix.exs b/mix.exs index 6a29648f..aa1a811f 100644 --- a/mix.exs +++ b/mix.exs @@ -1,7 +1,7 @@ defmodule Boombox.Mixfile do use Mix.Project - @version "0.2.4" + @version "0.2.5" @github_url "https://github.com/membraneframework/boombox" def project do @@ -51,7 +51,7 @@ defmodule Boombox.Mixfile do {:membrane_webrtc_plugin, "~> 0.25.0"}, {:membrane_mp4_plugin, "~> 0.36.0"}, {:membrane_realtimer_plugin, "~> 0.9.0"}, - {:membrane_http_adaptive_stream_plugin, "~> 0.19.0"}, + {:membrane_http_adaptive_stream_plugin, "~> 0.20.1"}, {:membrane_rtmp_plugin, "~> 0.27.2"}, {:membrane_rtsp_plugin, "~> 0.6.1"}, {:membrane_rtp_plugin, "~> 0.30.0"}, @@ -71,11 +71,7 @@ defmodule Boombox.Mixfile do {:membrane_simple_rtsp_server, "~> 0.1.5", only: :test}, {:image, "~> 0.54.0"}, {:async_test, github: "software-mansion-labs/elixir_async_test", only: :test}, - # {:playwright, "~> 1.49.1-alpha.1", only: :test}, - {:playwright, - github: "membraneframework-labs/playwright-elixir", - ref: "5c02249512fa543f5e619a69b7e5c9e046605fe5", - only: :test}, + {:playwright, "~> 1.49.1-alpha.2", only: :test}, {:burrito, "~> 1.0", runtime: burrito?(), optional: true}, {:ex_doc, ">= 0.0.0", only: :dev, runtime: false}, {:dialyxir, ">= 0.0.0", only: :dev, runtime: false}, @@ -199,10 +195,19 @@ defmodule Boombox.Mixfile do # with new symlinks pointing to bundlex's # priv/shared/precompiled directory defp restore_symlinks(release) do - base_dir = "#{__DIR__}/_build/dev/rel/boombox/lib" + base_dir = + Path.join([ + __DIR__, + "_build", + Atom.to_string(Mix.env()), + "rel", + Atom.to_string(release.name), + "lib" + ]) shared = - Path.wildcard("#{base_dir}/bundlex*/priv/shared/precompiled/*") + Path.join(base_dir, "bundlex*/priv/shared/precompiled/*") + |> Path.wildcard() |> Enum.map(&Path.relative_to(&1, base_dir)) |> Map.new(&{Path.basename(&1), &1}) @@ -210,20 +215,37 @@ defmodule Boombox.Mixfile do |> Enum.each(fn path -> name = Path.basename(path) - case shared[name] do - nil -> - :ok - - shared_dir -> - File.rm_rf!(path) - depth = path |> Path.relative_to(base_dir) |> Path.split() |> length() - ln = String.duplicate("../", depth - 1) <> shared_dir - dbg(path) - dbg(ln) - File.ln_s!(ln, path) + if Map.has_key?(shared, name) do + ln = + Path.join([base_dir, shared[name], "lib"]) + |> Path.relative_to(Path.dirname(path), force: true) + + File.rm_rf!(path) + File.ln_s!(ln, path) end end) + Path.join(base_dir, "bundlex*/priv/shared/precompiled/*/lib") + |> Path.wildcard() + |> Enum.map(fn lib_dir -> + File.ls!(lib_dir) + |> Enum.group_by(&(String.split(&1, ".") |> List.first())) + |> Enum.each(fn {_lib_name, libs} -> + lib_to_symlink_to = + Enum.max_by(libs, &String.length/1) + + libs + |> Enum.filter(&(&1 != lib_to_symlink_to)) + |> Enum.map(fn lib_to_replace -> + lib_to_replace_path = + Path.join(lib_dir, lib_to_replace) + + File.rm_rf!(lib_to_replace_path) + File.ln_s!(lib_to_symlink_to, lib_to_replace_path) + end) + end) + end) + release end end diff --git a/mix.lock b/mix.lock index 2e080039..214d6ad8 100644 --- a/mix.lock +++ b/mix.lock @@ -1,29 +1,29 @@ %{ "async_test": {:git, "https://github.com/software-mansion-labs/elixir_async_test.git", "4a877c222682ecbd53fb897971637bbb1bc5da6c", []}, - "bandit": {:hex, :bandit, "1.7.0", "d1564f30553c97d3e25f9623144bb8df11f3787a26733f00b21699a128105c0c", [:mix], [{:hpax, "~> 1.0", [hex: :hpax, repo: "hexpm", optional: false]}, {:plug, "~> 1.18", [hex: :plug, repo: "hexpm", optional: false]}, {:telemetry, "~> 0.4 or ~> 1.0", [hex: :telemetry, repo: "hexpm", optional: false]}, {:thousand_island, "~> 1.0", [hex: :thousand_island, repo: "hexpm", optional: false]}, {:websock, "~> 0.5", [hex: :websock, repo: "hexpm", optional: false]}], "hexpm", "3e2f7a98c7a11f48d9d8c037f7177cd39778e74d55c7af06fe6227c742a8168a"}, + "bandit": {:hex, :bandit, "1.8.0", "c2e93d7e3c5c794272fa4623124f827c6f24b643acc822be64c826f9447d92fb", [:mix], [{:hpax, "~> 1.0", [hex: :hpax, repo: "hexpm", optional: false]}, {:plug, "~> 1.18", [hex: :plug, repo: "hexpm", optional: false]}, {:telemetry, "~> 0.4 or ~> 1.0", [hex: :telemetry, repo: "hexpm", optional: false]}, {:thousand_island, "~> 1.0", [hex: :thousand_island, repo: "hexpm", optional: false]}, {:websock, "~> 0.5", [hex: :websock, repo: "hexpm", optional: false]}], "hexpm", "8458ff4eed20ff2a2ea69d4854883a077c33ea42b51f6811b044ceee0fa15422"}, "bimap": {:hex, :bimap, "1.3.0", "3ea4832e58dc83a9b5b407c6731e7bae87458aa618e6d11d8e12114a17afa4b3", [:mix], [], "hexpm", "bf5a2b078528465aa705f405a5c638becd63e41d280ada41e0f77e6d255a10b4"}, "bunch": {:hex, :bunch, "1.6.1", "5393d827a64d5f846092703441ea50e65bc09f37fd8e320878f13e63d410aec7", [:mix], [], "hexpm", "286cc3add551628b30605efbe2fca4e38cc1bea89bcd0a1a7226920b3364fe4a"}, "bunch_native": {:hex, :bunch_native, "0.5.0", "8ac1536789a597599c10b652e0b526d8833348c19e4739a0759a2bedfd924e63", [:mix], [{:bundlex, "~> 1.0", [hex: :bundlex, repo: "hexpm", optional: false]}], "hexpm", "24190c760e32b23b36edeb2dc4852515c7c5b3b8675b1a864e0715bdd1c8f80d"}, "bundlex": {:hex, :bundlex, "1.5.4", "3726acd463f4d31894a59bbc177c17f3b574634a524212f13469f41c4834a1d9", [:mix], [{:bunch, "~> 1.0", [hex: :bunch, repo: "hexpm", optional: false]}, {:elixir_uuid, "~> 1.2", [hex: :elixir_uuid, repo: "hexpm", optional: false]}, {:qex, "~> 0.5", [hex: :qex, repo: "hexpm", optional: false]}, {:req, ">= 0.4.0", [hex: :req, repo: "hexpm", optional: false]}, {:zarex, "~> 1.0", [hex: :zarex, repo: "hexpm", optional: false]}], "hexpm", "e745726606a560275182a8ac1c8ebd5e11a659bb7460d8abf30f397e59b4c5d2"}, "bunt": {:hex, :bunt, "1.0.0", "081c2c665f086849e6d57900292b3a161727ab40431219529f13c4ddcf3e7a44", [:mix], [], "hexpm", "dc5f86aa08a5f6fa6b8096f0735c4e76d54ae5c9fa2c143e5a1fc7c1cd9bb6b5"}, - "burrito": {:hex, :burrito, "1.3.0", "4be8504185250756ff4a8770d0c0d91dbfe518d2faa5f1888f13b00540028c59", [:mix], [{:jason, "~> 1.4", [hex: :jason, repo: "hexpm", optional: false]}, {:req, ">= 0.5.0", [hex: :req, repo: "hexpm", optional: false]}, {:typed_struct, "~> 0.2.0 or ~> 0.3.0", [hex: :typed_struct, repo: "hexpm", optional: false]}], "hexpm", "a53f6bc0644bfd998164d68714c9af04291c220f5f7d0c90cb9616780cc60165"}, + "burrito": {:hex, :burrito, "1.4.0", "f94fa1c3f174575bc4cad887a2940fd77469e1985c3a6633fcdcfa72f915caf2", [:mix], [{:jason, "~> 1.4", [hex: :jason, repo: "hexpm", optional: false]}, {:req, ">= 0.5.0", [hex: :req, repo: "hexpm", optional: false]}, {:typed_struct, "~> 0.2.0 or ~> 0.3.0", [hex: :typed_struct, repo: "hexpm", optional: false]}], "hexpm", "0fa052e6f446cd3e5ff7e00813452b09eeadeddb5ec5174c2976eb0e4ad88765"}, "castore": {:hex, :castore, "1.0.15", "8aa930c890fe18b6fe0a0cff27b27d0d4d231867897bd23ea772dee561f032a3", [:mix], [], "hexpm", "96ce4c69d7d5d7a0761420ef743e2f4096253931a3ba69e5ff8ef1844fe446d3"}, - "cc_precompiler": {:hex, :cc_precompiler, "0.1.10", "47c9c08d8869cf09b41da36538f62bc1abd3e19e41701c2cea2675b53c704258", [:mix], [{:elixir_make, "~> 0.7", [hex: :elixir_make, repo: "hexpm", optional: false]}], "hexpm", "f6e046254e53cd6b41c6bacd70ae728011aa82b2742a80d6e2214855c6e06b22"}, + "cc_precompiler": {:hex, :cc_precompiler, "0.1.11", "8c844d0b9fb98a3edea067f94f616b3f6b29b959b6b3bf25fee94ffe34364768", [:mix], [{:elixir_make, "~> 0.7", [hex: :elixir_make, repo: "hexpm", optional: false]}], "hexpm", "3427232caf0835f94680e5bcf082408a70b48ad68a5f5c0b02a3bea9f3a075b9"}, "certifi": {:hex, :certifi, "2.15.0", "0e6e882fcdaaa0a5a9f2b3db55b1394dba07e8d6d9bcad08318fb604c6839712", [:rebar3], [], "hexpm", "b147ed22ce71d72eafdad94f055165c1c182f61a2ff49df28bcc71d1d5b94a60"}, "coerce": {:hex, :coerce, "1.0.1", "211c27386315dc2894ac11bc1f413a0e38505d808153367bd5c6e75a4003d096", [:mix], [], "hexpm", "b44a691700f7a1a15b4b7e2ff1fa30bebd669929ac8aa43cffe9e2f8bf051cf1"}, "corsica": {:hex, :corsica, "2.1.3", "dccd094ffce38178acead9ae743180cdaffa388f35f0461ba1e8151d32e190e6", [:mix], [{:plug, "~> 1.0", [hex: :plug, repo: "hexpm", optional: false]}, {:telemetry, "~> 0.4.0 or ~> 1.0", [hex: :telemetry, repo: "hexpm", optional: false]}], "hexpm", "616c08f61a345780c2cf662ff226816f04d8868e12054e68963e95285b5be8bc"}, "cowlib": {:hex, :cowlib, "2.7.3", "a7ffcd0917e6d50b4d5fb28e9e2085a0ceb3c97dea310505f7460ff5ed764ce9", [:rebar3], [], "hexpm", "1e1a3d176d52daebbecbbcdfd27c27726076567905c2a9d7398c54da9d225761"}, "crc": {:hex, :crc, "0.10.5", "ee12a7c056ac498ef2ea985ecdc9fa53c1bfb4e53a484d9f17ff94803707dfd8", [:mix, :rebar3], [{:elixir_make, "~> 0.6", [hex: :elixir_make, repo: "hexpm", optional: false]}], "hexpm", "3e673b6495a9525c5c641585af1accba59a1eb33de697bedf341e247012c2c7f"}, "credo": {:hex, :credo, "1.7.12", "9e3c20463de4b5f3f23721527fcaf16722ec815e70ff6c60b86412c695d426c1", [: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", "8493d45c656c5427d9c729235b99d498bd133421f3e0a683e5c1b561471291e5"}, - "dialyxir": {:hex, :dialyxir, "1.4.5", "ca1571ac18e0f88d4ab245f0b60fa31ff1b12cbae2b11bd25d207f865e8ae78a", [:mix], [{:erlex, ">= 0.2.7", [hex: :erlex, repo: "hexpm", optional: false]}], "hexpm", "b0fb08bb8107c750db5c0b324fa2df5ceaa0f9307690ee3c1f6ba5b9eb5d35c3"}, + "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"}, "elixir_make": {:hex, :elixir_make, "0.9.0", "6484b3cd8c0cee58f09f05ecaf1a140a8c97670671a6a0e7ab4dc326c3109726", [:mix], [], "hexpm", "db23d4fd8b757462ad02f8aa73431a426fe6671c80b200d9710caf3d1dd0ffdb"}, "elixir_uuid": {:hex, :elixir_uuid, "1.2.1", "dce506597acb7e6b0daeaff52ff6a9043f5919a4c3315abb4143f0b00378c097", [:mix], [], "hexpm", "f7eba2ea6c3555cea09706492716b0d87397b88946e6380898c2889d68585752"}, "erlex": {:hex, :erlex, "0.2.7", "810e8725f96ab74d17aac676e748627a07bc87eb950d2b83acd29dc047a30595", [:mix], [], "hexpm", "3ed95f79d1a844c3f6bf0cea61e0d5612a42ce56da9c03f01df538685365efb0"}, "esbuild": {:hex, :esbuild, "0.8.2", "5f379dfa383ef482b738e7771daf238b2d1cfb0222bef9d3b20d4c8f06c7a7ac", [:mix], [{:castore, ">= 0.0.0", [hex: :castore, repo: "hexpm", optional: false]}, {:jason, "~> 1.4", [hex: :jason, repo: "hexpm", optional: false]}], "hexpm", "558a8a08ed78eb820efbfda1de196569d8bfa9b51e8371a1934fbb31345feda7"}, - "ex_doc": {:hex, :ex_doc, "0.38.2", "504d25eef296b4dec3b8e33e810bc8b5344d565998cd83914ffe1b8503737c02", [: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", "732f2d972e42c116a70802f9898c51b54916e542cc50968ac6980512ec90f42b"}, + "ex_doc": {:hex, :ex_doc, "0.38.4", "ab48dff7a8af84226bf23baddcdda329f467255d924380a0cf0cee97bb9a9ede", [: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", "f7b62346408a83911c2580154e35613eb314e0278aeea72ed7fedef9c1f165b2"}, "ex_dtls": {:hex, :ex_dtls, "0.16.0", "3ae38025ccc77f6db573e2e391602fa9bbc02253c137d8d2d59469a66cbe806b", [:mix], [{:bundlex, "~> 1.5.3", [hex: :bundlex, repo: "hexpm", optional: false]}, {:unifex, "~> 1.0", [hex: :unifex, repo: "hexpm", optional: false]}], "hexpm", "2a4e30d74c6ddf95cc5b796423293c06a0da295454c3823819808ff031b4b361"}, - "ex_hls": {:hex, :ex_hls, "0.0.1", "dd550f50f35433cd8c8cfe535148a6eacaccea9a0094bfa3c75f6eb6975d7617", [:mix], [{:ex_m3u8, "~> 0.15.3", [hex: :ex_m3u8, repo: "hexpm", optional: false]}, {:membrane_h26x_plugin, "~> 0.10.2", [hex: :membrane_h26x_plugin, repo: "hexpm", optional: false]}, {:membrane_mp4_plugin, "~> 0.36.0", [hex: :membrane_mp4_plugin, repo: "hexpm", optional: false]}, {:mpeg_ts, "~> 2.0.0", [hex: :mpeg_ts, repo: "hexpm", optional: false]}, {:qex, "~> 0.5.1", [hex: :qex, repo: "hexpm", optional: false]}, {:req, "~> 0.5.10", [hex: :req, repo: "hexpm", optional: false]}], "hexpm", "cbcb1391b5896ac1095db02e65dc94f84c74c54b833846a2ae55624d666d47e5"}, + "ex_hls": {:hex, :ex_hls, "0.1.2", "fca2c2a4ddf8459b9a47bf1fd6552c5d74cccf5dc72f56cf87129111c3e2f8ee", [:mix], [{:ex_m3u8, "~> 0.15.3", [hex: :ex_m3u8, repo: "hexpm", optional: false]}, {:membrane_h26x_plugin, "~> 0.10.2", [hex: :membrane_h26x_plugin, repo: "hexpm", optional: false]}, {:membrane_mp4_plugin, "~> 0.36.0", [hex: :membrane_mp4_plugin, repo: "hexpm", optional: false]}, {:mpeg_ts, "~> 2.0.0", [hex: :mpeg_ts, repo: "hexpm", optional: false]}, {:qex, "~> 0.5.1", [hex: :qex, repo: "hexpm", optional: false]}, {:req, "~> 0.5.10", [hex: :req, repo: "hexpm", optional: false]}], "hexpm", "8129921a863918999cda4032cf66e5e4de9fa24faa33cee28a09b34f13438a49"}, "ex_ice": {:hex, :ex_ice, "0.9.4", "793121989164e49d8dc64b82bcb7842a4c2e0d224a2f00379ab415293a78c8e7", [:mix], [{:elixir_uuid, "~> 1.0", [hex: :elixir_uuid, repo: "hexpm", optional: false]}, {:ex_stun, "~> 0.2.0", [hex: :ex_stun, repo: "hexpm", optional: false]}, {:ex_turn, "~> 0.2.0", [hex: :ex_turn, repo: "hexpm", optional: false]}], "hexpm", "fc328ed721c558440266def81a2cd5138d163164218ebe449fa9a10fcda72574"}, "ex_libsrt": {:hex, :ex_libsrt, "0.1.2", "a2e5e212382a7f004c6f0d0910fd9588c9da3d87a0dc4b60ab1b39321652d851", [:mix], [{:unifex, "~> 1.2.0", [hex: :unifex, repo: "hexpm", optional: false]}], "hexpm", "d599f7f1c0fd0e246be083557ae2001bf1f8edd457ad3af3ed037696c2573af0"}, "ex_libsrtp": {:hex, :ex_libsrtp, "0.7.2", "211bd89c08026943ce71f3e2c0231795b99cee748808ed3ae7b97cd8d2450b6b", [:mix], [{:bunch, "~> 1.6", [hex: :bunch, repo: "hexpm", optional: false]}, {:bundlex, "~> 1.3", [hex: :bundlex, repo: "hexpm", optional: false]}, {:membrane_precompiled_dependency_provider, "~> 0.1.0", [hex: :membrane_precompiled_dependency_provider, repo: "hexpm", optional: false]}, {:unifex, "~> 1.1", [hex: :unifex, repo: "hexpm", optional: false]}], "hexpm", "2e20645d0d739a4ecdcf8d4810a0c198120c8a2f617f2b75b2e2e704d59f492a"}, @@ -34,10 +34,10 @@ "ex_stun": {:hex, :ex_stun, "0.2.0", "feb1fc7db0356406655b2a617805e6c712b93308c8ea2bf0ba1197b1f0866deb", [:mix], [], "hexpm", "1e01ba8290082ccbf37acaa5190d1f69b51edd6de2026a8d6d51368b29d115d0"}, "ex_turn": {:hex, :ex_turn, "0.2.0", "4e1f9b089e9a5ee44928d12370cc9ea7a89b84b2f6256832de65271212eb80de", [:mix], [{:ex_stun, "~> 0.2.0", [hex: :ex_stun, repo: "hexpm", optional: false]}], "hexpm", "08e884f0af2c4a147e3f8cd4ffe33e3452a256389f0956e55a8c4d75bf0e74cd"}, "ex_webrtc": {:hex, :ex_webrtc, "0.8.1", "e507d1b3d89e9c8b74e3fef5f4070d57e20a3f77061b7439b1af1877d6577793", [:mix], [{:crc, "~> 0.10", [hex: :crc, repo: "hexpm", optional: false]}, {:ex_dtls, "~> 0.16.0", [hex: :ex_dtls, repo: "hexpm", optional: false]}, {:ex_ice, "~> 0.9.0", [hex: :ex_ice, repo: "hexpm", optional: false]}, {:ex_libsrtp, "~> 0.7.1", [hex: :ex_libsrtp, repo: "hexpm", optional: false]}, {:ex_rtcp, "~> 0.4.0", [hex: :ex_rtcp, repo: "hexpm", optional: false]}, {:ex_rtp, "~> 0.4.0", [hex: :ex_rtp, repo: "hexpm", optional: false]}, {:ex_sctp, "0.1.2", [hex: :ex_sctp, repo: "hexpm", optional: true]}, {:ex_sdp, "~> 1.0", [hex: :ex_sdp, repo: "hexpm", optional: false]}], "hexpm", "2c5563cdaf998b5beed3c79b0feeaa1430f30118b21ab59dd18289d72177adf0"}, - "file_system": {:hex, :file_system, "1.1.0", "08d232062284546c6c34426997dd7ef6ec9f8bbd090eb91780283c9016840e8f", [:mix], [], "hexpm", "bfcf81244f416871f2a2e15c1b515287faa5db9c6bcf290222206d120b3d43f6"}, + "file_system": {:hex, :file_system, "1.1.1", "31864f4685b0148f25bd3fbef2b1228457c0c89024ad67f7a81a3ffbc0bbad3a", [:mix], [], "hexpm", "7a15ff97dfe526aeefb090a7a9d3d03aa907e100e262a0f8f7746b78f8f87a5d"}, "finch": {:hex, :finch, "0.20.0", "5330aefb6b010f424dcbbc4615d914e9e3deae40095e73ab0c1bb0968933cadf", [:mix], [{:mime, "~> 1.0 or ~> 2.0", [hex: :mime, repo: "hexpm", optional: false]}, {:mint, "~> 1.6.2 or ~> 1.7", [hex: :mint, repo: "hexpm", optional: false]}, {:nimble_options, "~> 0.4 or ~> 1.0", [hex: :nimble_options, repo: "hexpm", optional: false]}, {:nimble_pool, "~> 1.1", [hex: :nimble_pool, repo: "hexpm", optional: false]}, {:telemetry, "~> 0.4 or ~> 1.0", [hex: :telemetry, repo: "hexpm", optional: false]}], "hexpm", "2658131a74d051aabfcba936093c903b8e89da9a1b63e430bee62045fa9b2ee2"}, "gun": {:hex, :gun, "1.3.3", "cf8b51beb36c22b9c8df1921e3f2bc4d2b1f68b49ad4fbc64e91875aa14e16b4", [:rebar3], [{:cowlib, "~> 2.7.0", [hex: :cowlib, repo: "hexpm", optional: false]}], "hexpm", "3106ce167f9c9723f849e4fb54ea4a4d814e3996ae243a1c828b256e749041e0"}, - "hackney": {:hex, :hackney, "1.24.1", "f5205a125bba6ed4587f9db3cc7c729d11316fa8f215d3e57ed1c067a9703fa9", [:rebar3], [{:certifi, "~> 2.15.0", [hex: :certifi, repo: "hexpm", optional: false]}, {:idna, "~> 6.1.0", [hex: :idna, repo: "hexpm", optional: false]}, {:metrics, "~> 1.0.0", [hex: :metrics, repo: "hexpm", optional: false]}, {:mimerl, "~> 1.4", [hex: :mimerl, repo: "hexpm", optional: false]}, {:parse_trans, "3.4.1", [hex: :parse_trans, repo: "hexpm", optional: false]}, {:ssl_verify_fun, "~> 1.1.0", [hex: :ssl_verify_fun, repo: "hexpm", optional: false]}, {:unicode_util_compat, "~> 0.7.0", [hex: :unicode_util_compat, repo: "hexpm", optional: false]}], "hexpm", "f4a7392a0b53d8bbc3eb855bdcc919cd677358e65b2afd3840b5b3690c4c8a39"}, + "hackney": {:hex, :hackney, "1.25.0", "390e9b83f31e5b325b9f43b76e1a785cbdb69b5b6cd4e079aa67835ded046867", [:rebar3], [{:certifi, "~> 2.15.0", [hex: :certifi, repo: "hexpm", optional: false]}, {:idna, "~> 6.1.0", [hex: :idna, repo: "hexpm", optional: false]}, {:metrics, "~> 1.0.0", [hex: :metrics, repo: "hexpm", optional: false]}, {:mimerl, "~> 1.4", [hex: :mimerl, repo: "hexpm", optional: false]}, {:parse_trans, "3.4.1", [hex: :parse_trans, repo: "hexpm", optional: false]}, {:ssl_verify_fun, "~> 1.1.0", [hex: :ssl_verify_fun, repo: "hexpm", optional: false]}, {:unicode_util_compat, "~> 0.7.1", [hex: :unicode_util_compat, repo: "hexpm", optional: false]}], "hexpm", "7209bfd75fd1f42467211ff8f59ea74d6f2a9e81cbcee95a56711ee79fd6b1d4"}, "heap": {:hex, :heap, "2.0.2", "d98cb178286cfeb5edbcf17785e2d20af73ca57b5a2cf4af584118afbcf917eb", [:mix], [], "hexpm", "ba9ea2fe99eb4bcbd9a8a28eaf71cbcac449ca1d8e71731596aace9028c9d429"}, "hpax": {:hex, :hpax, "1.0.3", "ed67ef51ad4df91e75cc6a1494f851850c0bd98ebc0be6e81b026e765ee535aa", [:mix], [], "hexpm", "8eab6e1cfa8d5918c2ce4ba43588e894af35dbd8e91e6e55c817bca5847df34a"}, "idna": {:hex, :idna, "6.1.1", "8a63070e9f7d0c62eb9d9fcb360a7de382448200fbbd1b106cc96d3d8099df8d", [:rebar3], [{:unicode_util_compat, "~> 0.7.0", [hex: :unicode_util_compat, repo: "hexpm", optional: false]}], "hexpm", "92376eb7894412ed19ac475e4a86f7b413c1b9fbb5bd16dccd57934157944cea"}, @@ -64,7 +64,7 @@ "membrane_h265_format": {:hex, :membrane_h265_format, "0.2.0", "1903c072cf7b0980c4d0c117ab61a2cd33e88782b696290de29570a7fab34819", [:mix], [], "hexpm", "6df418bdf242c0d9f7dbf2e5aea4c2d182e34ac9ad5a8b8cef2610c290002e83"}, "membrane_h26x_plugin": {:hex, :membrane_h26x_plugin, "0.10.5", "e9fa1ee9cda944259c4d2728c8b279bfe0152a3a6c1af187b07fa8411ca4e25e", [:mix], [{:bunch, "~> 1.4", [hex: :bunch, repo: "hexpm", optional: false]}, {:membrane_core, "~> 1.0", [hex: :membrane_core, repo: "hexpm", optional: false]}, {:membrane_h264_format, "~> 0.6.0", [hex: :membrane_h264_format, repo: "hexpm", optional: false]}, {:membrane_h265_format, "~> 0.2.0", [hex: :membrane_h265_format, repo: "hexpm", optional: false]}], "hexpm", "dd0287a6b6223e47bba30a8952d6ec53db35f6a3e33203b7ad786e995711f098"}, "membrane_hackney_plugin": {:hex, :membrane_hackney_plugin, "0.11.0", "54b368333a23394e7cac2f4d6b701bf8c5ee6614670a31f4ebe009b5e691a5c1", [:mix], [{:hackney, "~> 1.16", [hex: :hackney, repo: "hexpm", optional: false]}, {:membrane_core, "~> 1.0", [hex: :membrane_core, repo: "hexpm", optional: false]}, {:mockery, "~> 2.3", [hex: :mockery, repo: "hexpm", optional: false]}], "hexpm", "2b28fd1be3c889d5824d7d985598386c7673828c88f49a91221df3626af8a998"}, - "membrane_http_adaptive_stream_plugin": {:hex, :membrane_http_adaptive_stream_plugin, "0.19.0", "3a9c4ea3dfff31dd7501c06b1822f0a117d32ec0d876a593d48047e451bc1143", [:mix], [{:bunch, "~> 1.6", [hex: :bunch, repo: "hexpm", optional: false]}, {:ex_hls, "~> 0.0.1", [hex: :ex_hls, repo: "hexpm", optional: false]}, {:membrane_aac_plugin, "~> 0.19.0", [hex: :membrane_aac_plugin, repo: "hexpm", optional: false]}, {:membrane_core, "~> 1.2", [hex: :membrane_core, repo: "hexpm", optional: false]}, {:membrane_h26x_plugin, "~> 0.10.0", [hex: :membrane_h26x_plugin, repo: "hexpm", optional: false]}, {:membrane_mp4_plugin, "~> 0.36.0", [hex: :membrane_mp4_plugin, repo: "hexpm", optional: false]}, {:membrane_tee_plugin, "~> 0.12.0", [hex: :membrane_tee_plugin, repo: "hexpm", optional: false]}, {:qex, "~> 0.5", [hex: :qex, repo: "hexpm", optional: false]}], "hexpm", "f9b1dac7d732b2da206d1a633bbe793e4b9af708365c8c31c1695a5ec42da307"}, + "membrane_http_adaptive_stream_plugin": {:hex, :membrane_http_adaptive_stream_plugin, "0.20.1", "dc42d4b64f54bb8e658ee75096805ef110f4eb79644095bf9c4abd8118b827e1", [:mix], [{:bunch, "~> 1.6", [hex: :bunch, repo: "hexpm", optional: false]}, {:ex_hls, "~> 0.1.2", [hex: :ex_hls, repo: "hexpm", optional: false]}, {:membrane_aac_plugin, "~> 0.19.0", [hex: :membrane_aac_plugin, repo: "hexpm", optional: false]}, {:membrane_core, "~> 1.2", [hex: :membrane_core, repo: "hexpm", optional: false]}, {:membrane_h26x_plugin, "~> 0.10.0", [hex: :membrane_h26x_plugin, repo: "hexpm", optional: false]}, {:membrane_mp4_plugin, "~> 0.36.0", [hex: :membrane_mp4_plugin, repo: "hexpm", optional: false]}, {:membrane_tee_plugin, "~> 0.12.0", [hex: :membrane_tee_plugin, repo: "hexpm", optional: false]}, {:qex, "~> 0.5", [hex: :qex, repo: "hexpm", optional: false]}, {:stream_split, "~> 0.1.7", [hex: :stream_split, repo: "hexpm", optional: false]}], "hexpm", "66e7fcc1dcd1c51ebe09a7b6f9f4474a0bde19bacd5d632731500a4c105da0b8"}, "membrane_ivf_plugin": {:hex, :membrane_ivf_plugin, "0.8.0", "0495a4fd34a1b9841d288b3a078d2b09c48020294a6452ce08e8954711648ac8", [:mix], [{:membrane_core, "~> 1.0", [hex: :membrane_core, repo: "hexpm", optional: false]}, {:membrane_file_plugin, "~> 0.17.0", [hex: :membrane_file_plugin, repo: "hexpm", optional: false]}, {:membrane_vp8_format, "~> 0.5.0", [hex: :membrane_vp8_format, repo: "hexpm", optional: false]}, {:membrane_vp9_format, "~> 0.5.0", [hex: :membrane_vp9_format, repo: "hexpm", optional: false]}], "hexpm", "b17805a451f1066dab68c19577efad7819200c20970e3ba5f7d6fbbc751240e9"}, "membrane_mp3_lame_plugin": {:hex, :membrane_mp3_lame_plugin, "0.18.3", "441af1b5115c0d9cfc56023a25de42ee88d42ed9c4f4093bee344fe07d950e10", [:mix], [{:bunch, "~> 1.0", [hex: :bunch, repo: "hexpm", optional: false]}, {:bundlex, "~> 1.2", [hex: :bundlex, repo: "hexpm", optional: false]}, {:membrane_common_c, "~> 0.16.0", [hex: :membrane_common_c, repo: "hexpm", optional: false]}, {:membrane_core, "~> 1.0", [hex: :membrane_core, repo: "hexpm", optional: false]}, {:membrane_mpegaudio_format, "~> 0.3.0", [hex: :membrane_mpegaudio_format, repo: "hexpm", optional: false]}, {:membrane_precompiled_dependency_provider, "~> 0.1.0", [hex: :membrane_precompiled_dependency_provider, repo: "hexpm", optional: false]}, {:membrane_raw_audio_format, "~> 0.12.0", [hex: :membrane_raw_audio_format, repo: "hexpm", optional: false]}], "hexpm", "f25b985d7f80a7c721d1f127dc62c57ea4797d5f617e334766ed29f391187a6b"}, "membrane_mp3_mad_plugin": {:hex, :membrane_mp3_mad_plugin, "0.18.4", "30003dfbacfa92b51d5124107f9c502ee3f48d8dbc310d304d0164a819f8b8a8", [:mix], [{:bundlex, "~> 1.3", [hex: :bundlex, repo: "hexpm", optional: false]}, {:membrane_common_c, "~> 0.16.0", [hex: :membrane_common_c, repo: "hexpm", optional: false]}, {:membrane_core, "~> 1.0", [hex: :membrane_core, repo: "hexpm", optional: false]}, {:membrane_mpegaudio_format, "~> 0.3.0", [hex: :membrane_mpegaudio_format, repo: "hexpm", optional: false]}, {:membrane_precompiled_dependency_provider, "~> 0.1.0", [hex: :membrane_precompiled_dependency_provider, repo: "hexpm", optional: false]}, {:membrane_raw_audio_format, "~> 0.12.0", [hex: :membrane_raw_audio_format, repo: "hexpm", optional: false]}, {:unifex, "~> 1.1", [hex: :unifex, repo: "hexpm", optional: false]}], "hexpm", "dc78f5ca1bc52380add89a2d0cce9706e97d00abcfbdd46ad82afe44b745a43b"}, @@ -101,7 +101,7 @@ "membrane_udp_plugin": {:hex, :membrane_udp_plugin, "0.14.1", "18b807e85b01b8466ed2c7e23f35cd7f4db13ce6c8f1b3eaa23b7a6155de757f", [:mix], [{:membrane_core, "~> 1.0", [hex: :membrane_core, repo: "hexpm", optional: false]}], "hexpm", "ba7168c1436813c4c56f9aa1904997b9254b82db72a6573c8cd192e30bd452d5"}, "membrane_vp8_format": {:hex, :membrane_vp8_format, "0.5.0", "a589c20bb9d97ddc9b717684d00cefc84e2500ce63a0c33c4b9618d9b2f9b2ea", [:mix], [], "hexpm", "d29e0dae4bebc6838e82e031c181fe626d168c687e4bc617c1d0772bdeed19d5"}, "membrane_vp9_format": {:hex, :membrane_vp9_format, "0.5.0", "c6a4f2cbfc39dba5d80ad8287162c52b5cf6488676bd64435c1ac957bd16e66f", [:mix], [], "hexpm", "68752d8cbe7270ec222fc84a7d1553499f0d8ff86ef9d9e89f8955d49e20278e"}, - "membrane_vpx_plugin": {:hex, :membrane_vpx_plugin, "0.4.0", "911df2079ef20c28c945001b1f048556690ff3dd4b2d586a0c03d3ba03d83a34", [:mix], [{:membrane_core, "~> 1.0", [hex: :membrane_core, repo: "hexpm", optional: false]}, {:membrane_precompiled_dependency_provider, "~> 0.1.0", [hex: :membrane_precompiled_dependency_provider, repo: "hexpm", optional: false]}, {:membrane_raw_video_format, "~> 0.4.0", [hex: :membrane_raw_video_format, repo: "hexpm", optional: false]}, {:membrane_vp8_format, "~> 0.5.0", [hex: :membrane_vp8_format, repo: "hexpm", optional: false]}, {:membrane_vp9_format, "~> 0.5.0", [hex: :membrane_vp9_format, repo: "hexpm", optional: false]}, {:unifex, "~> 1.2", [hex: :unifex, repo: "hexpm", optional: false]}], "hexpm", "921f86af2ff0efe072fc1bce7873845fa9f02eebd27df5ed658c42d4d655b402"}, + "membrane_vpx_plugin": {:hex, :membrane_vpx_plugin, "0.4.1", "e1cacee1c0ba0f95f4b22c62c4a0dda506480d168167c389100c57ba2031359e", [:mix], [{:membrane_core, "~> 1.0", [hex: :membrane_core, repo: "hexpm", optional: false]}, {:membrane_precompiled_dependency_provider, "~> 0.1.0", [hex: :membrane_precompiled_dependency_provider, repo: "hexpm", optional: false]}, {:membrane_raw_video_format, "~> 0.4.0", [hex: :membrane_raw_video_format, repo: "hexpm", optional: false]}, {:membrane_vp8_format, "~> 0.5.0", [hex: :membrane_vp8_format, repo: "hexpm", optional: false]}, {:membrane_vp9_format, "~> 0.5.0", [hex: :membrane_vp9_format, repo: "hexpm", optional: false]}, {:unifex, "~> 1.2", [hex: :unifex, repo: "hexpm", optional: false]}], "hexpm", "f5d8306ea6e8e284f630b2db91071065031c476a4782c282ae9a2a7aa383b4b6"}, "membrane_wav_plugin": {:hex, :membrane_wav_plugin, "0.10.1", "f2827079070463f881f37844d5eaba8c7caaa5a9c44efc2dd7c3699d314c406d", [:mix], [{:membrane_core, "~> 1.0", [hex: :membrane_core, repo: "hexpm", optional: false]}, {:membrane_file_plugin, "~> 0.17.0", [hex: :membrane_file_plugin, repo: "hexpm", optional: true]}, {:membrane_raw_audio_format, "~> 0.12.0", [hex: :membrane_raw_audio_format, repo: "hexpm", optional: false]}], "hexpm", "0c2dad1e263728fc859fd0bb8165f85f0518f7bff3f218641ffe3cc9ae64cc7e"}, "membrane_webrtc_plugin": {:hex, :membrane_webrtc_plugin, "0.25.3", "895b740623387cd52cc7cb9e87c164fb78818aad434d040bc9b0aff3fe203162", [:mix], [{:bandit, "~> 1.2", [hex: :bandit, repo: "hexpm", optional: false]}, {:corsica, "~> 2.0", [hex: :corsica, repo: "hexpm", optional: false]}, {:ex_webrtc, "~> 0.8.0", [hex: :ex_webrtc, repo: "hexpm", optional: false]}, {:membrane_core, ">= 1.2.2 and < 2.0.0-0", [hex: :membrane_core, repo: "hexpm", optional: false]}, {:membrane_rtp_h264_plugin, "~> 0.20.1", [hex: :membrane_rtp_h264_plugin, repo: "hexpm", optional: false]}, {:membrane_rtp_opus_plugin, "~> 0.10.0", [hex: :membrane_rtp_opus_plugin, repo: "hexpm", optional: false]}, {:membrane_rtp_plugin, "~> 0.30.0", [hex: :membrane_rtp_plugin, repo: "hexpm", optional: false]}, {:membrane_rtp_vp8_plugin, "~> 0.9.4", [hex: :membrane_rtp_vp8_plugin, repo: "hexpm", optional: false]}, {:phoenix, ">= 0.0.0", [hex: :phoenix, repo: "hexpm", optional: true]}, {:phoenix_live_view, "~> 1.0", [hex: :phoenix_live_view, repo: "hexpm", optional: true]}, {:req, "~> 0.5", [hex: :req, repo: "hexpm", optional: false]}, {:websock_adapter, "~> 0.5.0", [hex: :websock_adapter, repo: "hexpm", optional: false]}], "hexpm", "31ac30233fc738ddd80eba668ecca84ebf0e28cb3322050514c1fbaad2cbff21"}, "metrics": {:hex, :metrics, "1.0.1", "25f094dea2cda98213cecc3aeff09e940299d950904393b2a29d191c346a8486", [:rebar3], [], "hexpm", "69b09adddc4f74a40716ae54d140f93beb0fb8978d8636eaded0c31b6f099f16"}, @@ -116,23 +116,24 @@ "numbers": {:hex, :numbers, "5.2.4", "f123d5bb7f6acc366f8f445e10a32bd403c8469bdbce8ce049e1f0972b607080", [:mix], [{:coerce, "~> 1.0", [hex: :coerce, repo: "hexpm", optional: false]}, {:decimal, "~> 1.9 or ~> 2.0", [hex: :decimal, repo: "hexpm", optional: true]}], "hexpm", "eeccf5c61d5f4922198395bf87a465b6f980b8b862dd22d28198c5e6fab38582"}, "parse_trans": {:hex, :parse_trans, "3.4.1", "6e6aa8167cb44cc8f39441d05193be6e6f4e7c2946cb2759f015f8c56b76e5ff", [:rebar3], [], "hexpm", "620a406ce75dada827b82e453c19cf06776be266f5a67cff34e1ef2cbb60e49a"}, "phoenix_html": {:hex, :phoenix_html, "4.2.1", "35279e2a39140068fc03f8874408d58eef734e488fc142153f055c5454fd1c08", [:mix], [], "hexpm", "cff108100ae2715dd959ae8f2a8cef8e20b593f8dfd031c9cba92702cf23e053"}, - "playwright": {:git, "https://github.com/membraneframework-labs/playwright-elixir.git", "5c02249512fa543f5e619a69b7e5c9e046605fe5", [ref: "5c02249512fa543f5e619a69b7e5c9e046605fe5"]}, + "playwright": {:hex, :playwright, "1.49.1-alpha.2", "911e7771f51874cca6d075b2c73e7a32e3d7e9b29dc38732f5121ac916cae35d", [:mix], [{:cowlib, "~> 2.7.0", [hex: :cowlib, repo: "hexpm", optional: false]}, {:elixir_uuid, "~> 1.2", [hex: :elixir_uuid, repo: "hexpm", optional: false]}, {:esbuild, "~> 0.8.1", [hex: :esbuild, repo: "hexpm", optional: false]}, {:gun, "~> 1.3.3", [hex: :gun, repo: "hexpm", optional: false]}, {:jason, "~> 1.4", [hex: :jason, repo: "hexpm", optional: false]}, {:recase, "~> 0.7", [hex: :recase, repo: "hexpm", optional: false]}], "hexpm", "492386163d6fd65967c39e4822478639e198bcf45e527253825f57d72867af52"}, "plug": {:hex, :plug, "1.18.1", "5067f26f7745b7e31bc3368bc1a2b818b9779faa959b49c934c17730efc911cf", [:mix], [{:mime, "~> 1.0 or ~> 2.0", [hex: :mime, repo: "hexpm", optional: false]}, {:plug_crypto, "~> 1.1.1 or ~> 1.2 or ~> 2.0", [hex: :plug_crypto, repo: "hexpm", optional: false]}, {:telemetry, "~> 0.4.3 or ~> 1.0", [hex: :telemetry, repo: "hexpm", optional: false]}], "hexpm", "57a57db70df2b422b564437d2d33cf8d33cd16339c1edb190cd11b1a3a546cc2"}, "plug_crypto": {:hex, :plug_crypto, "2.1.1", "19bda8184399cb24afa10be734f84a16ea0a2bc65054e23a62bb10f06bc89491", [:mix], [], "hexpm", "6470bce6ffe41c8bd497612ffde1a7e4af67f36a15eea5f921af71cf3e11247c"}, "qex": {:hex, :qex, "0.5.1", "0d82c0f008551d24fffb99d97f8299afcb8ea9cf99582b770bd004ed5af63fd6", [:mix], [], "hexpm", "935a39fdaf2445834b95951456559e9dc2063d0a055742c558a99987b38d6bab"}, "ratio": {:hex, :ratio, "4.0.1", "3044166f2fc6890aa53d3aef0c336f84b2bebb889dc57d5f95cc540daa1912f8", [:mix], [{:decimal, "~> 1.6 or ~> 2.0", [hex: :decimal, repo: "hexpm", optional: true]}, {:numbers, "~> 5.2.0", [hex: :numbers, repo: "hexpm", optional: false]}], "hexpm", "c60cbb3ccdff9ffa56e7d6d1654b5c70d9f90f4d753ab3a43a6bf40855b881ce"}, - "recase": {:hex, :recase, "0.8.1", "ab98cd35857a86fa5ca99036f575241d71d77d9c2ab0c39aacf1c9b61f6f7d1d", [:mix], [], "hexpm", "9fd8d63e7e43bd9ea385b12364e305778b2bbd92537e95c4b2e26fc507d5e4c2"}, + "recase": {:hex, :recase, "0.9.0", "437982693fdfbec125f11c8868eb3b4d32e9aa6995d3a68ac8686f3e2bf5d8d1", [:mix], [], "hexpm", "efa7549ebd128988d1723037a6f6a61948055aec107db6288f1c52830cb6501c"}, "req": {:hex, :req, "0.5.15", "662020efb6ea60b9f0e0fac9be88cd7558b53fe51155a2d9899de594f9906ba9", [:mix], [{:brotli, "~> 0.3.1", [hex: :brotli, repo: "hexpm", optional: true]}, {:ezstd, "~> 1.0", [hex: :ezstd, repo: "hexpm", optional: true]}, {:finch, "~> 0.17", [hex: :finch, repo: "hexpm", optional: false]}, {:jason, "~> 1.0", [hex: :jason, repo: "hexpm", optional: false]}, {:mime, "~> 2.0.6 or ~> 2.1", [hex: :mime, repo: "hexpm", optional: false]}, {:nimble_csv, "~> 1.0", [hex: :nimble_csv, repo: "hexpm", optional: true]}, {:plug, "~> 1.0", [hex: :plug, repo: "hexpm", optional: true]}], "hexpm", "a6513a35fad65467893ced9785457e91693352c70b58bbc045b47e5eb2ef0c53"}, "shmex": {:hex, :shmex, "0.5.1", "81dd209093416bf6608e66882cb7e676089307448a1afd4fc906c1f7e5b94cf4", [:mix], [{:bunch_native, "~> 0.5.0", [hex: :bunch_native, repo: "hexpm", optional: false]}, {:bundlex, "~> 1.0", [hex: :bundlex, repo: "hexpm", optional: false]}], "hexpm", "c29f8286891252f64c4e1dac40b217d960f7d58def597c4e606ff8fbe71ceb80"}, "ssl_verify_fun": {:hex, :ssl_verify_fun, "1.1.7", "354c321cf377240c7b8716899e182ce4890c5938111a1296add3ec74cf1715df", [:make, :mix, :rebar3], [], "hexpm", "fe4c190e8f37401d30167c8c405eda19469f34577987c76dde613e838bbc67f8"}, + "stream_split": {:hex, :stream_split, "0.1.7", "2d3fd1fd21697da7f91926768d65f79409086052c9ec7ae593987388f52425f8", [:mix], [], "hexpm", "1dc072ff507a64404a0ad7af90df97096183fee8eeac7b300320cea7c4679147"}, "sweet_xml": {:hex, :sweet_xml, "0.7.5", "803a563113981aaac202a1dbd39771562d0ad31004ddbfc9b5090bdcd5605277", [:mix], [], "hexpm", "193b28a9b12891cae351d81a0cead165ffe67df1b73fe5866d10629f4faefb12"}, "telemetry": {:hex, :telemetry, "1.3.0", "fedebbae410d715cf8e7062c96a1ef32ec22e764197f70cda73d82778d61e7a2", [:rebar3], [], "hexpm", "7015fc8919dbe63764f4b4b87a95b7c0996bd539e0d499be6ec9d7f3875b79e6"}, "telemetry_metrics": {:hex, :telemetry_metrics, "1.1.0", "5bd5f3b5637e0abea0426b947e3ce5dd304f8b3bc6617039e2b5a008adc02f8f", [:mix], [{:telemetry, "~> 0.4 or ~> 1.0", [hex: :telemetry, repo: "hexpm", optional: false]}], "hexpm", "e7b79e8ddfde70adb6db8a6623d1778ec66401f366e9a8f5dd0955c56bc8ce67"}, - "thousand_island": {:hex, :thousand_island, "1.3.14", "ad45ebed2577b5437582bcc79c5eccd1e2a8c326abf6a3464ab6c06e2055a34a", [:mix], [{:telemetry, "~> 0.4 or ~> 1.0", [hex: :telemetry, repo: "hexpm", optional: false]}], "hexpm", "d0d24a929d31cdd1d7903a4fe7f2409afeedff092d277be604966cd6aa4307ef"}, + "thousand_island": {:hex, :thousand_island, "1.4.1", "8df065e627407e281f7935da5ad0f3842d10eb721afa92e760b720d71e2e37aa", [:mix], [{:telemetry, "~> 0.4 or ~> 1.0", [hex: :telemetry, repo: "hexpm", optional: false]}], "hexpm", "204a8640e5d2818589b87286ae66160978628d7edf6095181cbe0440765fb6c1"}, "typed_struct": {:hex, :typed_struct, "0.3.0", "939789e3c1dca39d7170c87f729127469d1315dcf99fee8e152bb774b17e7ff7", [:mix], [], "hexpm", "c50bd5c3a61fe4e198a8504f939be3d3c85903b382bde4865579bc23111d1b6d"}, "unicode_util_compat": {:hex, :unicode_util_compat, "0.7.1", "a48703a25c170eedadca83b11e88985af08d35f37c6f664d6dcfb106a97782fc", [:rebar3], [], "hexpm", "b3a917854ce3ae233619744ad1e0102e05673136776fb2fa76234f3e03b23642"}, "unifex": {:hex, :unifex, "1.2.1", "6841c170a6e16509fac30b19e4e0a19937c33155a59088b50c15fc2c36251b6b", [:mix], [{:bunch, "~> 1.0", [hex: :bunch, repo: "hexpm", optional: false]}, {:bundlex, "~> 1.4", [hex: :bundlex, repo: "hexpm", optional: false]}, {:shmex, "~> 0.5.0", [hex: :shmex, repo: "hexpm", optional: false]}], "hexpm", "8c9d2e3c48df031e9995dd16865bab3df402c0295ba3a31f38274bb5314c7d37"}, - "vix": {:hex, :vix, "0.33.1", "72717f9b7a2ccd314c0b320a91d8cae67f100c0df378251acea19151fbf6e4b6", [:make, :mix], [{:castore, "~> 0.1 or ~> 1.0", [hex: :castore, repo: "hexpm", optional: false]}, {:cc_precompiler, "~> 0.1.4 or ~> 0.2", [hex: :cc_precompiler, repo: "hexpm", optional: false]}, {:elixir_make, "~> 0.7.3 or ~> 0.8", [hex: :elixir_make, repo: "hexpm", optional: false]}, {:kino, "~> 0.7", [hex: :kino, repo: "hexpm", optional: true]}], "hexpm", "d9143e03fcd7f2f0e4db9a86d4b64aca0e39e99c303059d5841450cc4481b29c"}, + "vix": {:hex, :vix, "0.35.0", "f6319b715e3b072e53eba456a21af5f2ff010a7a7b19b884600ea98a0609b18c", [:make, :mix], [{:cc_precompiler, "~> 0.1.4 or ~> 0.2", [hex: :cc_precompiler, repo: "hexpm", optional: false]}, {:elixir_make, "~> 0.7.3 or ~> 0.8", [hex: :elixir_make, repo: "hexpm", optional: false]}, {:kino, "~> 0.7", [hex: :kino, repo: "hexpm", optional: true]}], "hexpm", "a3e80067a89d0631b6cf2b93594e03c1b303a2c7cddbbdd28040750d521984e5"}, "websock": {:hex, :websock, "0.5.3", "2f69a6ebe810328555b6fe5c831a851f485e303a7c8ce6c5f675abeb20ebdadc", [:mix], [], "hexpm", "6105453d7fac22c712ad66fab1d45abdf049868f253cf719b625151460b8b453"}, "websock_adapter": {:hex, :websock_adapter, "0.5.8", "3b97dc94e407e2d1fc666b2fb9acf6be81a1798a2602294aac000260a7c4a47d", [:mix], [{:bandit, ">= 0.6.0", [hex: :bandit, repo: "hexpm", optional: true]}, {:plug, "~> 1.14", [hex: :plug, repo: "hexpm", optional: false]}, {:plug_cowboy, "~> 2.6", [hex: :plug_cowboy, repo: "hexpm", optional: true]}, {:websock, "~> 0.5", [hex: :websock, repo: "hexpm", optional: false]}], "hexpm", "315b9a1865552212b5f35140ad194e67ce31af45bcee443d4ecb96b5fd3f3782"}, "zarex": {:hex, :zarex, "1.0.5", "58239e3ee5d75f343262bb4df5cf466555a1c689f920e5d3651a9333972f7c7e", [:mix], [], "hexpm", "9fb72ef0567c2b2742f5119a1ba8a24a2fabb21b8d09820aefbf3e592fa9a46a"}, diff --git a/test/boombox_test.exs b/test/boombox_test.exs index 9d362437..ff1bcef5 100644 --- a/test/boombox_test.exs +++ b/test/boombox_test.exs @@ -29,87 +29,142 @@ defmodule BoomboxTest do file_file_mp4_video: {[@bbb_mp4_v, "output.mp4"], "ref_bun10s_aac.mp4", kinds: [:video]}, http_file_mp4: {[@bbb_mp4_url, "output.mp4"], "ref_bun10s_aac.mp4", []}, file_file_file_mp4: {[@bbb_mp4, "mid_output.mp4", "output.mp4"], "ref_bun10s_aac.mp4", []}, - file_webrtc: - {[@bbb_mp4, {:webrtc, quote(do: Membrane.WebRTC.Signaling.new())}, "output.mp4"], - "ref_bun10s_opus_aac.mp4", []}, + file_webrtc: { + quote do + [@bbb_mp4, {:webrtc, Membrane.WebRTC.Signaling.new()}, "output.mp4"] + end, + "ref_bun10s_opus_aac.mp4", + [] + }, file_whip: - {[@bbb_mp4, {:whip, quote(do: get_free_local_address())}, "output.mp4"], - "ref_bun10s_opus_aac.mp4", []}, + {quote do + [@bbb_mp4, {:whip, get_free_local_address(:http)}, "output.mp4"] + end, "ref_bun10s_opus_aac.mp4", []}, http_webrtc: - {[ - @bbb_mp4_url, - {:webrtc, quote(do: Membrane.WebRTC.Signaling.new())}, - "output.mp4" - ], "ref_bun10s_opus_aac.mp4", []}, + {quote do + [ + @bbb_mp4_url, + {:webrtc, Membrane.WebRTC.Signaling.new()}, + "output.mp4" + ] + end, "ref_bun10s_opus_aac.mp4", []}, webrtc_audio: - {[ - @bbb_mp4_a, - {:webrtc, quote(do: Membrane.WebRTC.Signaling.new())}, - "output.mp4" - ], "ref_bun10s_opus_aac.mp4", [kinds: [:audio]]}, + {quote do + [ + @bbb_mp4_a, + {:webrtc, Membrane.WebRTC.Signaling.new()}, + "output.mp4" + ] + end, "ref_bun10s_opus_aac.mp4", [kinds: [:audio]]}, webrtc_video: - {[ - @bbb_mp4_v, - {:webrtc, quote(do: Membrane.WebRTC.Signaling.new())}, - "output.mp4" - ], "ref_bun10s_opus_aac.mp4", [kinds: [:video]]}, + {quote do + [ + @bbb_mp4_v, + {:webrtc, Membrane.WebRTC.Signaling.new()}, + "output.mp4" + ] + end, "ref_bun10s_opus_aac.mp4", [kinds: [:video]]}, webrtc_webrtc: - {[ - @bbb_mp4, - {:webrtc, quote(do: Membrane.WebRTC.Signaling.new())}, - {:webrtc, quote(do: Membrane.WebRTC.Signaling.new())}, - "output.mp4" - ], "ref_bun10s_opus_aac.mp4", []}, + {quote do + [ + @bbb_mp4, + {:webrtc, Membrane.WebRTC.Signaling.new()}, + {:webrtc, Membrane.WebRTC.Signaling.new()}, + "output.mp4" + ] + end, "ref_bun10s_opus_aac.mp4", []}, hls_fmp4_mp4: {[@bbb_hls_fmp4_url, "output.mp4"], "bun_hls.mp4", []}, hls_fmp4_webrtc: - {[ - @bbb_hls_fmp4_url, - {:webrtc, quote(do: Membrane.WebRTC.Signaling.new())}, - "output.mp4" - ], "bun_hls_webrtc.mp4", []}, + {quote do + [ + @bbb_hls_fmp4_url, + {:webrtc, Membrane.WebRTC.Signaling.new()}, + "output.mp4" + ] + end, "bun_hls_webrtc.mp4", []}, hls_mpegts_mp4: {[@bbb_hls_mpegts_url, "output.mp4"], "bun_hls_mpegts.mp4", []}, - mp4_srt_mp4: {[@bbb_mp4, {:srt, "srt://127.0.0.1:9710"}, "output.mp4"], "bun10s.mp4", []}, + mp4_srt_mp4: + {quote do + [ + @bbb_mp4, + {:srt, get_free_local_address(:srt)}, + "output.mp4" + ] + end, "bun10s.mp4", []}, mp4_a_srt_mp4: - {[@bbb_mp4_a, {:srt, "srt://127.0.0.1:9710"}, "output.mp4"], "bun10s.mp4", - [kinds: [:audio]]}, + {quote do + [ + @bbb_mp4_a, + {:srt, get_free_local_address(:srt)}, + "output.mp4" + ] + end, "bun10s.mp4", [kinds: [:audio]]}, mp4_v_srt_mp4: - {[@bbb_mp4_v, {:srt, "srt://127.0.0.1:9710"}, "output.mp4"], "bun10s.mp4", - [kinds: [:video]]}, + {quote do + [ + @bbb_mp4_v, + {:srt, get_free_local_address(:srt)}, + "output.mp4" + ] + end, "bun10s.mp4", [kinds: [:video]]}, mp4_srt_mp4_with_auth: - {[ - @bbb_mp4, - quote( - do: - {:srt, "srt://127.0.0.1:9710", - [stream_id: "some_stream_id", password: "some_password"]} - ), - "output.mp4" - ], "bun10s.mp4", []}, + {quote do + [ + @bbb_mp4, + {:srt, get_free_local_address(:srt), + [stream_id: "some_stream_id", password: "some_password"]}, + "output.mp4" + ] + end, "bun10s.mp4", []}, mp4_a_srt_mp4_with_auth: - {[ - @bbb_mp4_a, - quote( - do: - {:srt, "srt://127.0.0.1:9710", - [stream_id: "some_stream_id", password: "some_password"]} - ), - "output.mp4" - ], "bun10s.mp4", [kinds: [:audio]]}, + {quote do + [ + @bbb_mp4_a, + {:srt, get_free_local_address(:srt), + [stream_id: "some_stream_id", password: "some_password"]}, + "output.mp4" + ] + end, "bun10s.mp4", [kinds: [:audio]]}, mp4_v_srt_mp4_with_auth: - {[ - @bbb_mp4_v, - quote( - do: - {:srt, "srt://127.0.0.1:9710", - [stream_id: "some_stream_id", password: "some_password"]} - ), - "output.mp4" - ], "bun10s.mp4", [kinds: [:video]]} + {quote do + [ + @bbb_mp4_v, + {:srt, get_free_local_address(:srt), + [stream_id: "some_stream_id", password: "some_password"]}, + "output.mp4" + ] + end, "bun10s.mp4", [kinds: [:video]]}, + live_hls_mp4: + {quote do + [@bbb_mp4_url, {:hls, "index.m3u8", mode: :live}, "output.mp4"] + end, "bun_hls.mp4", []}, + hls_fmp4_live_hls_webrtc_mp4: + {quote do + [ + @bbb_hls_fmp4_url, + {:hls, "index.m3u8", mode: :live}, + {:webrtc, Membrane.WebRTC.Signaling.new()}, + "output.mp4" + ] + end, "bun_hls_webrtc.mp4", []}, + vod_hls_mp4: + {quote do + [@bbb_mp4_url, {:hls, "index.m3u8", mode: :vod}, "output.mp4"] + end, "bun_hls.mp4", []}, + hls_fmp4_vod_hls_webrtc_mp4: + {quote do + [ + @bbb_hls_fmp4_url, + {:hls, "index.m3u8", mode: :vod}, + {:webrtc, Membrane.WebRTC.Signaling.new()}, + "output.mp4" + ] + end, "bun_hls_webrtc.mp4", []} ] |> Enum.each(fn {tag, {endpoints, fixture, compare_opts}} -> @tag tag async_test "#{tag}", %{tmp_dir: tmp_dir} do - endpoints = unquote(endpoints) |> parse_endpoint_paths(tmp_dir) + endpoints = unquote(endpoints) |> parse_endpoints(tmp_dir) endpoints |> Enum.chunk_every(2, 1, :discard) @@ -119,6 +174,11 @@ defmodule BoomboxTest do boombox_task = Boombox.async(input: input, output: output) [boombox_task] + [input, {:hls, playlist, mode: :live} = output] -> + boombox_task = Boombox.async(input: input, output: output) + await_until_file_exists!(playlist) + [boombox_task] + [{:srt, _url} = input, output] -> boombox_task = Boombox.async(input: input, output: output) [boombox_task] @@ -131,7 +191,7 @@ defmodule BoomboxTest do Boombox.run(input: input, output: output) [] end) - |> Task.await_many() + |> Task.await_many(15_000) compare_opts = [tmp_dir: tmp_dir] ++ unquote(compare_opts) @@ -161,24 +221,40 @@ defmodule BoomboxTest do defp file_endpoint?(_other), do: false + defp hls_endpoint?({:hls, _playlist} = _endpoint), do: true + defp hls_endpoint?({:hls, _playlist, _opts} = _endpoint), do: true + defp hls_endpoint?(uri) when is_binary(uri), do: String.ends_with?(uri, ".m3u8") + defp hls_endpoint?({uri, _opts}) when is_binary(uri), do: String.ends_with?(uri, ".m3u8") + defp hls_endpoint?(_other), do: false + + defp order_requiring_endpoint?(endpoint), + do: file_endpoint?(endpoint) or hls_endpoint?(endpoint) + # This function sorts endpoint pairs in the following manner: # * it splits the whole endpoint pairs list into the smallest chunks possible - # such that each chunk starts with the file input and ends with the file output - # * it reverses the endpoint pairs in each chunk + # such that each chunk starts with the file or HLS input and ends with the file + # or HLS output + # * reverses the order of endpoint pairs within each chunk + # * so that: + # - if pair A and pair B are in the same chunk and originally A was before B, + # then in the final list B will be before A + # - if pair A and pair B are in different chunks and originally A was before B, + # then in the final list A will be before B as well # It means that all the Boomboxes in each chunk are started in reversed # order so we can be sure that e.g. the listening socket of a SRT server # is spawned before the SRT client tries to connect to it + defp sort_endpoint_pairs(endpoint_pairs, to_reverse \\ []) defp sort_endpoint_pairs([[input, output] = endpoints_pair | rest], to_reverse) do cond do - file_endpoint?(input) and file_endpoint?(output) -> + order_requiring_endpoint?(input) and order_requiring_endpoint?(output) -> [endpoints_pair] ++ sort_endpoint_pairs(rest) - file_endpoint?(input) and to_reverse == [] -> + order_requiring_endpoint?(input) and to_reverse == [] -> sort_endpoint_pairs(rest, [endpoints_pair]) - file_endpoint?(output) -> + order_requiring_endpoint?(output) -> [endpoints_pair | to_reverse] ++ sort_endpoint_pairs(rest) true -> @@ -190,19 +266,35 @@ defmodule BoomboxTest do to_reverse end - defp parse_endpoint_paths([head | tail], tmp_dir) do + defp parse_endpoints([head | tail], tmp_dir) do modified_tail = - Enum.map(tail, fn endpoint -> - if is_binary(endpoint), - do: Path.join(tmp_dir, endpoint), - else: endpoint + Enum.map(tail, fn + endpoint when is_binary(endpoint) -> Path.join(tmp_dir, endpoint) + {:hls, playlist, opts} -> {:hls, Path.join(tmp_dir, playlist), opts} + {:srt, uri, opts} -> {:srt, uri <> ":#{get_free_port()}", opts} + {:srt, uri} -> {:srt, uri <> ":#{get_free_port()}"} + endpoint -> endpoint end) [head | modified_tail] end - defp get_free_local_address() do - "http://127.0.0.1:#{get_free_port()}" + defp await_until_file_exists!(file, seconds \\ 20) do + cond do + File.exists?(file) -> + :ok + + seconds <= 0 -> + raise "File #{file} not created within timeout" + + true -> + Process.sleep(1_000) + await_until_file_exists!(file, seconds - 1) + end + end + + defp get_free_local_address(protocol) do + "#{protocol}://127.0.0.1:#{get_free_port()}" end defp get_free_port() do