Stabilizza live YouTube/RTMP e fix crash rotazione mobile.

Pipeline YouTube con relay, overlay e publisher sync lato backend; fix GL pauseGlDuringRotation su Android per evitare crash in rotazione durante lo streaming Flutter.

Co-authored-by: Cursor <cursoragent@cursor.com>
This commit is contained in:
2026-06-06 15:30:55 +02:00
parent 1058c644bd
commit 854738b46d
65 changed files with 2606 additions and 579 deletions

View File

@@ -0,0 +1,80 @@
# Avvia overlay ffmpeg solo in Sidekiq (un solo job per sessione alla volta).
class OverlayRelayEnsureJob < ApplicationJob
queue_as :default
LOCK_KEY = "overlay_ensure:lock:%s"
LOCK_TTL = 55
RETRY_WAIT = 5.seconds
class << self
def enqueue_unique(session_id, attempt: 1, force_restart: false, wait: 0.seconds)
key = format(LOCK_KEY, session_id)
r = Redis.new(url: ENV.fetch("REDIS_URL", "redis://localhost:6379/0"))
return unless r.set(key, "1", nx: true, ex: LOCK_TTL)
set(wait: wait).perform_later(session_id, attempt, force_restart: force_restart)
end
end
def perform(session_id, attempt = 1, force_restart: false)
session = StreamSession.find_by(id: session_id)
unless session && !session.terminal?
clear_lock(session_id)
return
end
return unless session.status.in?(%w[live connecting reconnecting paused])
begin
run_ensure(session, session_id, attempt, force_restart)
ensure
clear_lock(session_id)
end
end
private
def run_ensure(session, session_id, attempt, force_restart)
if Mediamtx::PublisherOnline.video_publishing?(session) && !session.paused?
session.go_live! if session.may_go_live?
session.reconnect! if session.reconnecting? && session.may_reconnect?
Mediamtx::Client.new.set_always_available(session, enabled: false)
end
if force_restart
Streams::OverlayRelay.stop(session)
Streams::OverlayRelay.terminate_all_session_processes!(session.id)
end
Streams::OverlayRelay.ensure_publishing!(session)
if Streams::OverlayRelay.healthy?(session)
Youtube::LivePipeline.schedule_activate!(session, force: true, wait: 5.seconds)
return
end
return if Streams::OverlayRelay.running?(session.id)
Rails.logger.info("[OverlayRelayEnsureJob] overlay not running, retry session=#{session_id} attempt=#{attempt}")
reschedule(session_id, attempt, false) if attempt < 30
rescue Mediamtx::Client::Error => e
Rails.logger.warn("[OverlayRelayEnsureJob] session=#{session_id}: #{e.message}")
end
def reschedule(session_id, attempt, force_restart)
clear_lock(session_id)
self.class.enqueue_unique(
session_id,
attempt: attempt + 1,
force_restart: force_restart,
wait: RETRY_WAIT
)
end
def clear_lock(session_id)
redis.del(format(LOCK_KEY, session_id))
end
def redis
@redis ||= Redis.new(url: ENV.fetch("REDIS_URL", "redis://localhost:6379/0"))
end
end