Mantiene la copertina YouTube se il telefono cade e avvia ffmpeg sul nodo, non via SSH.

Il relay HLS→RTMPS resta sul worker/agent del nodo assegnato, così tre dirette contemporanee restano in onda sul sito e sul canale della società senza schermo nero.

Co-authored-by: Cursor <cursoragent@cursor.com>
This commit is contained in:
2026-08-16 20:41:46 +02:00
co-authored by Cursor
parent bfb3115a64
commit baa6283a15
36 changed files with 1444 additions and 141 deletions
@@ -77,9 +77,8 @@ module Streams
dns.upsert_a(hostname, ip)
simulated = instance.raw.is_a?(Hash) && (instance.raw[:simulated] || instance.raw["simulated"])
api_base = simulated ? home.api_base_url : "http://#{private_ip}:9997"
internal_rtmp = simulated ? home.internal_rtmp_url : "rtmp://#{private_ip}:1935"
internal_hls = simulated ? home.internal_hls_url : "http://#{private_ip}:8888"
urls = urls_for_node(role: role, home: home, hostname: hostname, simulated: simulated,
private_ip: private_ip, public_ip: ip, use_node_hostname: use_node_hostname)
StreamNode.create!(
slug: slug,
@@ -88,11 +87,11 @@ module Streams
status: "ready",
provider: provider_name_for(cloud, role: role),
provider_instance_id: instance.id,
rtmp_base_url: use_node_hostname ? "rtmp://#{hostname}:1935" : home.rtmp_base_url,
hls_base_url: use_node_hostname ? "https://#{hostname}/hls" : home.hls_base_url,
api_base_url: api_base,
internal_rtmp_url: internal_rtmp,
internal_hls_url: internal_hls,
rtmp_base_url: urls.fetch(:rtmp_base_url),
hls_base_url: urls.fetch(:hls_base_url),
api_base_url: urls.fetch(:api_base_url),
internal_rtmp_url: urls.fetch(:internal_rtmp_url),
internal_hls_url: urls.fetch(:internal_hls_url),
max_publishers: max,
max_relays: max,
last_health_at: Time.current,
@@ -105,6 +104,39 @@ module Streams
)
end
def urls_for_node(role:, home:, hostname:, simulated:, private_ip:, public_ip: nil, use_node_hostname:)
if role == "lab" && ENV["MEDIAMTX_LAB_API_URL"].present?
return {
api_base_url: ENV.fetch("MEDIAMTX_LAB_API_URL"),
internal_rtmp_url: ENV.fetch("MEDIAMTX_LAB_INTERNAL_RTMP_URL", "rtmp://mediamtx_lab:1935"),
internal_hls_url: ENV.fetch("MEDIAMTX_LAB_HLS_URL", "http://mediamtx_lab:8888"),
rtmp_base_url: ENV.fetch("MEDIAMTX_LAB_RTMP_URL", "rtmp://127.0.0.1:11935"),
# HLS pubblico resta sul proxy del sito: il controller instrada al MediaMTX del nodo.
hls_base_url: home.hls_base_url
}
end
control_ip = control_ip_for(role: role, private_ip: private_ip, public_ip: public_ip)
{
api_base_url: simulated ? home.api_base_url : "http://#{control_ip}:9997",
internal_rtmp_url: simulated ? home.internal_rtmp_url : "rtmp://#{control_ip}:1935",
internal_hls_url: simulated ? home.internal_hls_url : "http://#{control_ip}:8888",
rtmp_base_url: use_node_hostname ? "rtmp://#{hostname}:1935" : home.rtmp_base_url,
# Player del sito: proxy Rails/edge. HTTPS diretto sul nodo arriva dopo TLS/Caddy.
hls_base_url: home.hls_base_url
}
end
# Senza WireGuard/network privata Rails deve parlare con l'IPv4 pubblico (API+HLS).
def control_ip_for(role:, private_ip:, public_ip:)
public_ip = public_ip.presence
return private_ip if role != "cloud" || public_ip.blank?
return public_ip if ENV["STREAM_CLOUD_PUBLIC_CONTROL"] == "1"
return public_ip if private_ip.blank? || private_ip == public_ip
private_ip
end
def next_slug(prefix)
used = StreamNode.where("slug LIKE ?", "#{prefix}-%").pluck(:slug)
n = 1