You've already forked tribes-plugin-sender
forked from tribes/tribes-plugin-template
3e288a7e95
Rename Sender plugin identity to tribe-one-sender across manifest, runtime API routes, metrics, e2e fixtures, and tests.
218 lines
6.9 KiB
Elixir
218 lines
6.9 KiB
Elixir
defmodule TribeOne.TribesPlugin.Sender.Plugin do
|
|
@moduledoc """
|
|
Tribes plugin entry point.
|
|
"""
|
|
|
|
use Tribes.Plugin.Base, otp_app: :tribe_one_sender
|
|
|
|
@impl true
|
|
def register(context) do
|
|
super(context)
|
|
|> Map.merge(%{
|
|
nav_items: [
|
|
%{
|
|
label: "Streaming",
|
|
path: "/sender",
|
|
icon: nil,
|
|
requires: [],
|
|
order: 50
|
|
}
|
|
],
|
|
pages: [
|
|
%{
|
|
path: "/sender",
|
|
live_view: TribeOne.TribesPlugin.SenderWeb.HomeLive,
|
|
layout: nil
|
|
}
|
|
],
|
|
children: TribeOne.TribesPlugin.Sender.Application.children(),
|
|
api_routes: [
|
|
{"streams", TribeOne.TribesPlugin.SenderWeb.StreamingAPIPlug},
|
|
{"player-events", TribeOne.TribesPlugin.SenderWeb.StreamingAPIPlug}
|
|
],
|
|
management_methods: [
|
|
%{
|
|
name: "capabilities",
|
|
version: "1",
|
|
module: TribeOne.TribesPlugin.Sender.Management.Capabilities,
|
|
action: :call,
|
|
auth: :admin,
|
|
description: "Describe Sender management capabilities."
|
|
},
|
|
%{
|
|
name: "stream.get_default",
|
|
version: "1",
|
|
module: TribeOne.TribesPlugin.Sender.Management.Stream,
|
|
action: :get_default,
|
|
auth: :admin,
|
|
description: "Fetch the default Sender stream."
|
|
},
|
|
%{
|
|
name: "stream.ensure_default",
|
|
version: "1",
|
|
module: TribeOne.TribesPlugin.Sender.Management.Stream,
|
|
action: :ensure_default,
|
|
auth: :admin,
|
|
description: "Create the default Sender stream if it does not exist."
|
|
},
|
|
%{
|
|
name: "stream.update_default",
|
|
version: "1",
|
|
module: TribeOne.TribesPlugin.Sender.Management.Stream,
|
|
action: :update_default,
|
|
auth: :admin,
|
|
description: "Update the default Sender stream."
|
|
},
|
|
%{
|
|
name: "stream_key.create",
|
|
version: "1",
|
|
module: TribeOne.TribesPlugin.Sender.Management.StreamKey,
|
|
action: :create,
|
|
auth: :admin,
|
|
description: "Create an OBS stream key and return it once.",
|
|
sensitive_response?: true
|
|
},
|
|
%{
|
|
name: "media_endpoints.upsert",
|
|
version: "1",
|
|
module: TribeOne.TribesPlugin.Sender.Management.Topology,
|
|
action: :upsert_endpoint,
|
|
auth: :admin,
|
|
description: "Create or update a Sender media endpoint."
|
|
},
|
|
%{
|
|
name: "renditions.upsert",
|
|
version: "1",
|
|
module: TribeOne.TribesPlugin.Sender.Management.Topology,
|
|
action: :upsert_rendition,
|
|
auth: :admin,
|
|
description: "Create or update Sender rendition metadata."
|
|
},
|
|
%{
|
|
name: "stream.start",
|
|
version: "1",
|
|
module: TribeOne.TribesPlugin.Sender.Management.StreamLifecycle,
|
|
action: :start,
|
|
auth: :admin,
|
|
description: "Start the default stream in origin_ingest or hls_edge mode."
|
|
},
|
|
%{
|
|
name: "stream.stop",
|
|
version: "1",
|
|
module: TribeOne.TribesPlugin.Sender.Management.StreamLifecycle,
|
|
action: :stop,
|
|
auth: :admin,
|
|
description: "Stop the active Sender stream generation."
|
|
},
|
|
%{
|
|
name: "stream.status",
|
|
version: "1",
|
|
module: TribeOne.TribesPlugin.Sender.Management.StreamLifecycle,
|
|
action: :status,
|
|
auth: :admin,
|
|
description: "Return current Sender stream and session status."
|
|
},
|
|
%{
|
|
name: "endpoint_snapshots.report",
|
|
version: "1",
|
|
module: TribeOne.TribesPlugin.Sender.Management.EndpointSnapshots,
|
|
action: :report,
|
|
auth: :admin,
|
|
description: "Report current endpoint stats for playback routing."
|
|
}
|
|
],
|
|
metrics: [
|
|
%{
|
|
name: "viewer_count",
|
|
stat: "max",
|
|
query:
|
|
"sum by (tribes_external_node_id) (max_over_time(vinyl_hls_active_viewers[60s])) or max_over_time(plugins_tribe_one_sender_viewer_count[60s])",
|
|
description: "Estimated active Sender viewers on this node",
|
|
event_name: [:tribe_one_sender, :metrics, :viewer_count],
|
|
measurement: :value,
|
|
max_series: 16
|
|
},
|
|
%{
|
|
name: "playlist_requests",
|
|
stat: "sum",
|
|
query:
|
|
"sum by (tribes_external_node_id) (increase(vinyl_hls_playlist_requests_total[60s]))",
|
|
description: "Sender HLS playlist requests during the rollup bucket",
|
|
max_series: 16
|
|
},
|
|
%{
|
|
name: "hls_log_parse_errors",
|
|
stat: "sum",
|
|
query:
|
|
"sum by (tribes_external_node_id) (increase(vinyl_hls_log_parse_errors_total[60s]))",
|
|
description: "Vinyl HLS log parse errors during the rollup bucket",
|
|
max_series: 16
|
|
}
|
|
],
|
|
plugs: [
|
|
{"/sender/hls", TribeOne.TribesPlugin.SenderWeb.HLSPlug, []}
|
|
],
|
|
hooks: %{},
|
|
ash_domains: [TribeOne.TribesPlugin.Sender.Streaming],
|
|
config_schema: %{
|
|
title: "Sender",
|
|
description: "RTMP ingest and HLS playback defaults for this Tribes cluster.",
|
|
groups: [
|
|
%{
|
|
id: "playback",
|
|
label: "Playback",
|
|
description: "Browser playback and HLS latency defaults.",
|
|
order: 10,
|
|
settings: [
|
|
%{
|
|
key: "playback.low_latency",
|
|
label: "Low latency HLS",
|
|
description: "Prefer low-latency playlist behavior when available.",
|
|
type: :boolean,
|
|
default: true,
|
|
order: 10
|
|
},
|
|
%{
|
|
key: "playback.target_duration_ms",
|
|
label: "Target duration",
|
|
description: "Preferred HLS segment target duration.",
|
|
type: :integer,
|
|
default: 2_000,
|
|
min: 500,
|
|
max: 10_000,
|
|
step: 100,
|
|
unit: "ms",
|
|
order: 20
|
|
}
|
|
]
|
|
},
|
|
%{
|
|
id: "player",
|
|
label: "Player",
|
|
description: "Default behavior for embedded Sender players.",
|
|
order: 20,
|
|
settings: [
|
|
%{
|
|
key: "player.autoplay",
|
|
label: "Autoplay",
|
|
description: "Start playback automatically when the browser allows it.",
|
|
type: :boolean,
|
|
default: false,
|
|
order: 10
|
|
},
|
|
%{
|
|
key: "player.muted",
|
|
label: "Start muted",
|
|
description: "Begin playback muted by default.",
|
|
type: :boolean,
|
|
default: true,
|
|
order: 20
|
|
}
|
|
]
|
|
}
|
|
]
|
|
}
|
|
})
|
|
end
|
|
end
|