Skip to content

Commit

Permalink
Fix compositor (#93)
Browse files Browse the repository at this point in the history
* Prefix env vars with JF

* Fix incorrect JF_HOST convertion

* Add HOST_PORT env var

* Update .env.sample and Dockerfile env vars

* add missing libs

---------

Co-authored-by: Michał Śledź <[email protected]>
  • Loading branch information
roznawsk and mickel8 authored Sep 22, 2023
1 parent de72443 commit fe48e33
Show file tree
Hide file tree
Showing 6 changed files with 148 additions and 79 deletions.
81 changes: 69 additions & 12 deletions .env.sample
Original file line number Diff line number Diff line change
@@ -1,19 +1,76 @@
# used by the server e.g. to create tokens
SECRET_KEY_BASE=super-secret-key
# JF_IP and JF_PORT defines ip and port
# our HTTP endpoint socket will listen to.
# The default for Docker builds is 0.0.0.0 to allow
# access from the outside of container.
# Note that this cannot be 127.0.0.1 as
# in Docker it only allows for traffic
# from within the container.
# For other builds, it is 127.0.0.1 not to
# accidentaly expose Jellyfish to the outside world
# when it runs behind some proxy like nginx.
#
# JF_IP=0.0.0.0
# JF_PORT=5002

# true, if WebRTC peers are used
WEBRTC_USED=true

# hostname used to generate URLs throught the server
VIRTUAL_HOST=localhost
PORT=5002
SERVER_API_TOKEN=development
# JF_HOST and JF_HOST_PORT defines how Jellyfish
# should be seen from the outside.
# When you run Jellyfish behind proxy, your
# Jellyfish will run on 127.0.0.1 or 0.0.0.0
# (see JF_IP and JF_PORT for more information)
# but you don't want to and in fact you can't
# use those addresses for generating URLs, or
# telling Jellyfish Client to which server instance it
# should connect to (when running Jellyfish in a cluster).
# That's why we have separate environment variables.
#
# Example
#
# You run Jellyfish on a machine with some public
# ip address `PUB_IP` and domain `DOMAIN`.
# You most likely want to provide the following
# configuration when running Jellyfish using Docker
#
# JF_HOST=$DOMAIN or $PUB_IP
# JF_HOST_PORT=443
# JF_IP = 0.0.0.0
# JF_PORT = 5002
#
# JF_IP and JF_PORT are set by default
# so everything you need to set is JF_HOST and JF_HOST_PORT
#
JF_HOST=localhost
JF_HOST_PORT=443

# JF_METRICS_IP=0.0.0.0
# JF_METRICS_PORT=9568

# Token used for authorizing HTTP requests
JF_SERVER_API_TOKEN=jellyfish_docker_token

# Used by the server e.g. to create client tokens.
# If not set, it will be generated
# JF_SECRET_KEY_BASE=super-secret-key

# Decide if jellyfish will check origin of requests
# CHECK_ORIGIN=false
# JF_CHECK_ORIGIN=true

# Where Jellyfish should save its artifacts
# You can get access to this directory e.g. by mounting
# a volume with:
#
# -v $(pwd)/jellyfish_output:/app/jellyfish_output
#
# JF_OUTPUT_BASE_PATH=/app/jellyfish_output


# WEBRTC ENVS

# true, if WebRTC peers are used
JF_WEBRTC_USED=true

# TURN default configuration
# note: loopback address as INTEGRATED_TURN_IP cannot be used inside a Docker container
INTEGRATED_TURN_IP=<your_public_ip_address>
INTEGRATED_TURN_LISTEN_IP=0.0.0.0
INTEGRATED_TURN_PORT_RANGE=50000-65355
JF_INTEGRATED_TURN_IP=<your_public_ip_address>
JF_INTEGRATED_TURN_LISTEN_IP=0.0.0.0
JF_INTEGRATED_TURN_PORT_RANGE=50000-59_999
65 changes: 35 additions & 30 deletions Dockerfile
Original file line number Diff line number Diff line change
Expand Up @@ -56,31 +56,31 @@ RUN addgroup -S jellyfish && adduser -S jellyfish -G jellyfish
# https://github.com/docker-library/redis/blob/master/7.0/Dockerfile#L6
ENV GOSU_VERSION 1.16
RUN set -eux; \
\
apk add --no-cache --virtual .gosu-deps \
ca-certificates \
dpkg \
gnupg \
; \
\
dpkgArch="$(dpkg --print-architecture | awk -F- '{ print $NF }')"; \
wget -O /usr/local/bin/gosu "https://github.com/tianon/gosu/releases/download/$GOSU_VERSION/gosu-$dpkgArch"; \
wget -O /usr/local/bin/gosu.asc "https://github.com/tianon/gosu/releases/download/$GOSU_VERSION/gosu-$dpkgArch.asc"; \
\
# verify the signature
export GNUPGHOME="$(mktemp -d)"; \
gpg --batch --keyserver hkps://keys.openpgp.org --recv-keys B42F6819007F00F88E364FD4036A9C25BF357DD4; \
gpg --batch --verify /usr/local/bin/gosu.asc /usr/local/bin/gosu; \
command -v gpgconf && gpgconf --kill all || :; \
rm -rf "$GNUPGHOME" /usr/local/bin/gosu.asc; \
\
# clean up fetch dependencies
apk del --no-network .gosu-deps; \
\
chmod +x /usr/local/bin/gosu; \
# verify that the binary works
gosu --version; \
gosu nobody true
\
apk add --no-cache --virtual .gosu-deps \
ca-certificates \
dpkg \
gnupg \
; \
\
dpkgArch="$(dpkg --print-architecture | awk -F- '{ print $NF }')"; \
wget -O /usr/local/bin/gosu "https://github.com/tianon/gosu/releases/download/$GOSU_VERSION/gosu-$dpkgArch"; \
wget -O /usr/local/bin/gosu.asc "https://github.com/tianon/gosu/releases/download/$GOSU_VERSION/gosu-$dpkgArch.asc"; \
\
# verify the signature
export GNUPGHOME="$(mktemp -d)"; \
gpg --batch --keyserver hkps://keys.openpgp.org --recv-keys B42F6819007F00F88E364FD4036A9C25BF357DD4; \
gpg --batch --verify /usr/local/bin/gosu.asc /usr/local/bin/gosu; \
command -v gpgconf && gpgconf --kill all || :; \
rm -rf "$GNUPGHOME" /usr/local/bin/gosu.asc; \
\
# clean up fetch dependencies
apk del --no-network .gosu-deps; \
\
chmod +x /usr/local/bin/gosu; \
# verify that the binary works
gosu --version; \
gosu nobody true

RUN \
apk add --no-cache \
Expand All @@ -89,19 +89,24 @@ RUN \
ffmpeg \
fdk-aac \
opus \
curl
curl \
ncurses \
mesa \
mesa-dri-gallium \
mesa-dev

WORKDIR /app

# base path where jellyfish saves its artefacts
ENV OUTPUT_BASE_PATH=./jellyfish_output
ENV JF_OUTPUT_BASE_PATH=./jellyfish_output

# override default (127, 0, 0, 1) IP by 0.0.0.0
# as docker doesn't allow for connections outside the
# container when we listen to 127.0.0.1
ENV IP=0.0.0.0
ENV JF_IP=0.0.0.0
ENV JF_METRICS_IP=0.0.0.0

RUN mkdir ${OUTPUT_BASE_PATH} && chown jellyfish:jellyfish ${OUTPUT_BASE_PATH}
RUN mkdir ${JF_OUTPUT_BASE_PATH} && chown jellyfish:jellyfish ${JF_OUTPUT_BASE_PATH}

COPY --from=build /app/_build/prod/rel/jellyfish ./

Expand All @@ -110,7 +115,7 @@ RUN chmod +x docker-entrypoint.sh

ENV HOME=/app

HEALTHCHECK CMD curl --fail -H "authorization: Bearer ${SERVER_API_TOKEN}" http://localhost:${PORT}/room || exit 1
HEALTHCHECK CMD curl --fail -H "authorization: Bearer ${JF_SERVER_API_TOKEN}" http://localhost:${JF_PORT}/room || exit 1

ENTRYPOINT ["./docker-entrypoint.sh"]

Expand Down
65 changes: 36 additions & 29 deletions config/runtime.exs
Original file line number Diff line number Diff line change
Expand Up @@ -11,62 +11,69 @@ alias Jellyfish.ConfigReader
config :ex_dtls, impl: :nif
config :opentelemetry, traces_exporter: :none

hosts = ConfigReader.read_nodes("NODES")
nodes = ConfigReader.read_nodes("JF_NODES")

if hosts do
if nodes do
config :libcluster,
topologies: [
epmd_cluster: [
strategy: Cluster.Strategy.Epmd,
config: [hosts: hosts]
config: [hosts: nodes]
]
]
end

prod? = config_env() == :prod

ip =
ConfigReader.read_ip("JF_IP") ||
Application.get_env(:jellyfish, JellyfishWeb.Endpoint)[:http][:ip]

port =
ConfigReader.read_port("JF_PORT") ||
Application.get_env(:jellyfish, JellyfishWeb.Endpoint)[:http][:port]

host =
case System.get_env("HOST") do
nil when prod? -> raise "Unset HOST environment variable"
nil -> "localhost"
case System.get_env("JF_HOST") do
nil -> :inet.ntoa(ip) |> to_string()
other -> other
end

port =
ConfigReader.read_port("PORT") ||
Application.get_env(:jellyfish, JellyfishWeb.Endpoint)[:http][:port]
host_port =
case ConfigReader.read_port("JF_HOST_PORT") do
nil -> port
other -> other
end

config :jellyfish,
webrtc_used: ConfigReader.read_boolean("WEBRTC_USED") || true,
integrated_turn_ip: ConfigReader.read_ip("INTEGRATED_TURN_IP") || {127, 0, 0, 1},
integrated_turn_listen_ip: ConfigReader.read_ip("INTEGRATED_TURN_LISTEN_IP") || {127, 0, 0, 1},
webrtc_used: ConfigReader.read_boolean("JF_WEBRTC_USED") || true,
integrated_turn_ip: ConfigReader.read_ip("JF_INTEGRATED_TURN_IP") || {127, 0, 0, 1},
integrated_turn_listen_ip:
ConfigReader.read_ip("JF_INTEGRATED_TURN_LISTEN_IP") || {127, 0, 0, 1},
integrated_turn_port_range:
ConfigReader.read_port_range("INTEGRATED_TURN_PORT_RANGE") || {50_000, 59_999},
integrated_turn_tcp_port: ConfigReader.read_port("INTEGRATED_TURN_TCP_PORT"),
ConfigReader.read_port_range("JF_INTEGRATED_TURN_PORT_RANGE") || {50_000, 59_999},
integrated_turn_tcp_port: ConfigReader.read_port("JF_INTEGRATED_TURN_TCP_PORT"),
jwt_max_age: 24 * 3600,
output_base_path: System.get_env("OUTPUT_BASE_PATH", "jellyfish_output") |> Path.expand(),
address: System.get_env("JELLYFISH_ADDRESS") || "#{host}:#{port}",
metrics_ip: ConfigReader.read_ip("METRICS_IP") || {127, 0, 0, 1},
metrics_port: ConfigReader.read_port("METRICS_PORT") || 9568
output_base_path: System.get_env("JF_OUTPUT_BASE_PATH", "jellyfish_output") |> Path.expand(),
address: "#{host}:#{host_port}",
metrics_ip: ConfigReader.read_ip("JF_METRICS_IP") || {127, 0, 0, 1},
metrics_port: ConfigReader.read_port("JF_METRICS_PORT") || 9568

config :jellyfish, JellyfishWeb.Endpoint,
secret_key_base:
System.get_env("SECRET_KEY_BASE") || Base.encode64(:crypto.strong_rand_bytes(48)),
http: [port: port]
System.get_env("JF_SECRET_KEY_BASE") || Base.encode64(:crypto.strong_rand_bytes(48)),
http: [ip: ip, port: port],
url: [host: host, port: host_port]

if check_origin = ConfigReader.read_boolean("CHECK_ORIGIN") do
if check_origin = ConfigReader.read_boolean("JF_CHECK_ORIGIN") do
config :jellyfish, JellyfishWeb.Endpoint, check_origin: check_origin
end

if ip = ConfigReader.read_ip("IP") do
config :jellyfish, JellyfishWeb.Endpoint, http: [ip: ip]
end

case System.get_env("SERVER_API_TOKEN") do
case System.get_env("JF_SERVER_API_TOKEN") do
nil when prod? == true ->
raise """
environment variable SERVER_API_TOKEN is missing.
SERVER_API_TOKEN is used for HTTP requests and
environment variable JF_SERVER_API_TOKEN is missing.
JF_SERVER_API_TOKEN is used for HTTP requests and
server WebSocket authorization.
"""

Expand All @@ -78,5 +85,5 @@ case System.get_env("SERVER_API_TOKEN") do
end

if prod? do
config :jellyfish, JellyfishWeb.Endpoint, url: [host: host, port: 443, scheme: "https"]
config :jellyfish, JellyfishWeb.Endpoint, url: [scheme: "https"]
end
10 changes: 5 additions & 5 deletions docker-compose.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -4,9 +4,9 @@ x-jellyfish-template: &jellyfish-template
build: .
environment: &jellyfish-environment
ERLANG_COOKIE: "panuozzo-pollo-e-pancetta"
SERVER_API_TOKEN: "development"
HOST: "localhost"
NODES: "app@app1 app@app2"
JF_SERVER_API_TOKEN: "development"
JF_HOST: "localhost"
JF_NODES: "app@app1 app@app2"
networks:
- net1
restart: on-failure
Expand Down Expand Up @@ -37,7 +37,7 @@ services:
<<: *jellyfish-environment
RELEASE_NODE: app@app1
NODE_NAME: app@app1
PORT: 4001
JF_PORT: 4001
ports:
- 4001:4001

Expand All @@ -47,7 +47,7 @@ services:
<<: *jellyfish-environment
RELEASE_NODE: app@app2
NODE_NAME: app@app2
PORT: 4002
JF_PORT: 4002
ports:
- 4002:4002

Expand Down
2 changes: 1 addition & 1 deletion mix.exs
Original file line number Diff line number Diff line change
Expand Up @@ -75,7 +75,7 @@ defmodule Jellyfish.MixProject do

# HLS endpoints deps
{:membrane_audio_mix_plugin, "~> 0.15.2"},
{:membrane_video_compositor_plugin, "~> 0.5.1"},
{:membrane_video_compositor_plugin, "~> 0.5.4"},

# Dialyzer and credo
{:dialyxir, ">= 0.0.0", only: :dev, runtime: false},
Expand Down
4 changes: 2 additions & 2 deletions mix.lock
Original file line number Diff line number Diff line change
Expand Up @@ -37,7 +37,7 @@
"membrane_audio_mix_plugin": {:hex, :membrane_audio_mix_plugin, "0.15.2", "6f52ccf1a052115f509520fe24261b547121e87a4c5e55b7245c0aabbfcb5ddc", [:mix], [{:bunch, "~> 1.3", [hex: :bunch, repo: "hexpm", optional: false]}, {:membrane_common_c, "~> 0.15.0", [hex: :membrane_common_c, repo: "hexpm", optional: false]}, {:membrane_core, "~> 0.12.1", [hex: :membrane_core, repo: "hexpm", optional: false]}, {:membrane_raw_audio_format, "~> 0.11.0", [hex: :membrane_raw_audio_format, repo: "hexpm", optional: false]}, {:unifex, "~> 1.0", [hex: :unifex, repo: "hexpm", optional: false]}], "hexpm", "06c29679b2ec997597519665d5f2c621800003fe8f0069b2e478a4771b3e44ba"},
"membrane_cmaf_format": {:hex, :membrane_cmaf_format, "0.7.0", "573bfff6acf2371c5046b9174569f6316f4205e3d6e13e814bf7e613e5653a54", [:mix], [], "hexpm", "4ac6a24a33f61347a2714c982a5f84aa6207641f4de2ad5afde68a8b800da8de"},
"membrane_common_c": {:hex, :membrane_common_c, "0.15.0", "4b6005c562bf025e4a53c95a9646a9f5fa993ac440dd44c1a4d1ea210ec53793", [:mix], [{:membrane_core, "~> 0.12.0", [hex: :membrane_core, repo: "hexpm", optional: false]}, {:shmex, "~> 0.5.0", [hex: :shmex, repo: "hexpm", optional: false]}, {:unifex, "~> 1.0", [hex: :unifex, repo: "hexpm", optional: false]}], "hexpm", "f9584cca9865ed754b8333e362d49d6c449c708d7c87be6c5f7bd5a1d978d6bf"},
"membrane_core": {:hex, :membrane_core, "0.12.8", "59fdd10a1c1c6757302748d029fba4936257e53c93ac49fddd094962c08180f9", [:mix], [{:bunch, "~> 1.6", [hex: :bunch, repo: "hexpm", optional: false]}, {:qex, "~> 0.3", [hex: :qex, repo: "hexpm", optional: false]}, {:ratio, "~> 2.0", [hex: :ratio, repo: "hexpm", optional: false]}, {:telemetry, "~> 1.0", [hex: :telemetry, repo: "hexpm", optional: false]}], "hexpm", "d48ab1adc13d5820182b016cc397692ed5568d4064b5765c343b4d64c7f119e7"},
"membrane_core": {:hex, :membrane_core, "0.12.9", "b80239deacf98f24cfd2e0703b632e92ddded8b989227cd6e724140f433b0aac", [:mix], [{:bunch, "~> 1.6", [hex: :bunch, repo: "hexpm", optional: false]}, {:qex, "~> 0.3", [hex: :qex, repo: "hexpm", optional: false]}, {:ratio, "~> 2.0", [hex: :ratio, repo: "hexpm", optional: false]}, {:telemetry, "~> 1.0", [hex: :telemetry, repo: "hexpm", optional: false]}], "hexpm", "389b4b22da0e35d5b053ec2fa87bf36882e0ab88f8fb841af895982fb4abe504"},
"membrane_file_plugin": {:hex, :membrane_file_plugin, "0.15.0", "ddf9535fda82aae5b0688a98de1d02268287ffc8bcc6dba1a85e057d71c522af", [:mix], [{:membrane_core, "~> 0.12.0", [hex: :membrane_core, repo: "hexpm", optional: false]}], "hexpm", "fa2f7219f96c9e815475dc0d8c238c0a5648012917584756eb3eee476f737ce2"},
"membrane_framerate_converter_plugin": {:hex, :membrane_framerate_converter_plugin, "0.7.0", "f1a12b914dde380f43ca83363431ed3c743cf20320afe6011f0f77e97d1d867f", [:mix], [{:bunch, "~> 1.3", [hex: :bunch, repo: "hexpm", optional: false]}, {:membrane_core, "~> 0.12.0", [hex: :membrane_core, repo: "hexpm", optional: false]}, {:membrane_raw_video_format, "~> 0.3.0", [hex: :membrane_raw_video_format, repo: "hexpm", optional: false]}, {:ratio, "~> 2.4.2", [hex: :ratio, repo: "hexpm", optional: false]}], "hexpm", "6c552f839f047d392adec7ce06ee6c720ef0561d6a766ff7087df7950501b835"},
"membrane_funnel_plugin": {:hex, :membrane_funnel_plugin, "0.8.0", "fe735a88e4ac815041f3aba0bbfa25297769c4cb8b501f3875809698fe3f8fbf", [:mix], [{:membrane_core, "~> 0.12.0", [hex: :membrane_core, repo: "hexpm", optional: false]}], "hexpm", "61776c7e5b87eaa33eb314d06440cd124246a794482bf0c1b8cd2b796714f420"},
Expand Down Expand Up @@ -66,7 +66,7 @@
"membrane_tee_plugin": {:hex, :membrane_tee_plugin, "0.11.0", "7891283843fb42df788793217cc4117aa054de515b5e8a5b45109f069976e264", [:mix], [{:bunch, "~> 1.0", [hex: :bunch, repo: "hexpm", optional: false]}, {:membrane_core, "~> 0.12.0", [hex: :membrane_core, repo: "hexpm", optional: false]}], "hexpm", "1af8aff9488eb2303f18757a58d8d4a872f967fe66d2470e055e3c38dc770e88"},
"membrane_telemetry_metrics": {:hex, :membrane_telemetry_metrics, "0.1.0", "cb93d28356b436b0597736c3e4153738d82d2a14ff547f831df7e9051e54fc06", [:mix], [{:telemetry, "~> 1.0", [hex: :telemetry, repo: "hexpm", optional: false]}, {:telemetry_metrics, "~> 0.6.1", [hex: :telemetry_metrics, repo: "hexpm", optional: false]}], "hexpm", "aba28dc8311f70ced95d984509be930fac55857d2d18bffcf768815e627be3f0"},
"membrane_udp_plugin": {:hex, :membrane_udp_plugin, "0.10.0", "d2d207e5873298fad59a7c520a01a39179b2f31ec0cf8b63f0c6687bcd32a816", [:mix], [{:membrane_core, "~> 0.12.0", [hex: :membrane_core, repo: "hexpm", optional: false]}, {:mockery, "~> 2.3.0", [hex: :mockery, repo: "hexpm", optional: false]}], "hexpm", "55f5c55fb12966236c7c8cc078fbf3ad216ba457a6089092fdca55238d0e038b"},
"membrane_video_compositor_plugin": {:hex, :membrane_video_compositor_plugin, "0.5.3", "f7680c064b8ddedbc0f89e9c82325c78c7deee0ab636cfc88d28db8882f51abe", [:mix], [{:membrane_core, "~> 0.12.5", [hex: :membrane_core, repo: "hexpm", optional: false]}, {:membrane_framerate_converter_plugin, "~> 0.7.0", [hex: :membrane_framerate_converter_plugin, repo: "hexpm", optional: false]}, {:membrane_raw_video_format, "~> 0.3.0", [hex: :membrane_raw_video_format, repo: "hexpm", optional: false]}, {:qex, "~> 0.5.1", [hex: :qex, repo: "hexpm", optional: false]}, {:ratio, "~> 2.0", [hex: :ratio, repo: "hexpm", optional: false]}, {:rustler, "~> 0.26.0", [hex: :rustler, repo: "hexpm", optional: false]}, {:unifex, "~> 1.0", [hex: :unifex, repo: "hexpm", optional: false]}], "hexpm", "96eb0615fa02252efd4e35d4df3befc0af4de9cc8cc3620bbe65bdbddd83d99c"},
"membrane_video_compositor_plugin": {:hex, :membrane_video_compositor_plugin, "0.5.4", "bb30c2c964983f7e1a71b8151ddf5524f045c4525bbc9b1dc49af22273e8064a", [:mix], [{:membrane_core, "~> 0.12.5", [hex: :membrane_core, repo: "hexpm", optional: false]}, {:membrane_framerate_converter_plugin, "~> 0.7.0", [hex: :membrane_framerate_converter_plugin, repo: "hexpm", optional: false]}, {:membrane_raw_video_format, "~> 0.3.0", [hex: :membrane_raw_video_format, repo: "hexpm", optional: false]}, {:qex, "~> 0.5.1", [hex: :qex, repo: "hexpm", optional: false]}, {:ratio, "~> 2.0", [hex: :ratio, repo: "hexpm", optional: false]}, {:rustler, "~> 0.26.0", [hex: :rustler, repo: "hexpm", optional: false]}, {:unifex, "~> 1.0", [hex: :unifex, repo: "hexpm", optional: false]}], "hexpm", "8e19726a4a462bb29cb89d4fc44ade7a647439a4f8e4df940062a7b6f00ac44a"},
"membrane_vp8_format": {:hex, :membrane_vp8_format, "0.4.0", "6c29ec67479edfbab27b11266dc92f18f3baf4421262c5c31af348c33e5b92c7", [:mix], [], "hexpm", "8bb005ede61db8fcb3535a883f32168b251c2dfd1109197c8c3b39ce28ed08e2"},
"membrane_webrtc_plugin": {:hex, :membrane_webrtc_plugin, "0.16.1", "5532866fc022953a16a49d10cbf95ce4a28393d7b0447c439f3e25b3e1673884", [:mix], [{:bunch, "~> 1.5", [hex: :bunch, repo: "hexpm", optional: false]}, {:ex_libsrtp, ">= 0.0.0", [hex: :ex_libsrtp, repo: "hexpm", optional: false]}, {:ex_sdp, "~> 0.11.0", [hex: :ex_sdp, repo: "hexpm", optional: false]}, {:membrane_core, "~> 0.12.1", [hex: :membrane_core, repo: "hexpm", optional: false]}, {:membrane_funnel_plugin, "~> 0.8.0", [hex: :membrane_funnel_plugin, repo: "hexpm", optional: false]}, {:membrane_h264_plugin, "~> 0.7.2", [hex: :membrane_h264_plugin, repo: "hexpm", optional: false]}, {:membrane_ice_plugin, "~> 0.16.0", [hex: :membrane_ice_plugin, repo: "hexpm", optional: false]}, {:membrane_opentelemetry, "~> 0.1.0", [hex: :membrane_opentelemetry, repo: "hexpm", optional: false]}, {:membrane_rtp_format, "~> 0.7.0", [hex: :membrane_rtp_format, repo: "hexpm", optional: false]}, {:membrane_rtp_h264_plugin, "~> 0.18.0", [hex: :membrane_rtp_h264_plugin, repo: "hexpm", optional: false]}, {:membrane_rtp_opus_plugin, "~> 0.8.0", [hex: :membrane_rtp_opus_plugin, repo: "hexpm", optional: false]}, {:membrane_rtp_plugin, "~> 0.23.0", [hex: :membrane_rtp_plugin, repo: "hexpm", optional: false]}, {:membrane_rtp_vp8_plugin, "~> 0.8.0", [hex: :membrane_rtp_vp8_plugin, repo: "hexpm", optional: false]}, {:opentelemetry, "~> 1.0.4", [hex: :opentelemetry, repo: "hexpm", optional: false]}, {:opentelemetry_api, "~> 1.0", [hex: :opentelemetry_api, repo: "hexpm", optional: false]}, {:qex, "~> 0.5.0", [hex: :qex, repo: "hexpm", optional: false]}], "hexpm", "34546f499218a5fc4fa206b81591c12c1a8bf34f979b01f6fc26c20e5632338c"},
"metrics": {:hex, :metrics, "1.0.1", "25f094dea2cda98213cecc3aeff09e940299d950904393b2a29d191c346a8486", [:rebar3], [], "hexpm", "69b09adddc4f74a40716ae54d140f93beb0fb8978d8636eaded0c31b6f099f16"},
Expand Down

0 comments on commit fe48e33

Please sign in to comment.