Fix YouTube waiting: transcode verso RTMP e sync stato live.

Il relay non usa più copy (stream inactive su YouTube); PublisherSync
nel refresh overlay; activate solo quando lo stream YouTube è active.

Co-authored-by: Cursor <cursoragent@cursor.com>
This commit is contained in:
2026-06-04 08:32:30 +02:00
parent 2c5f4f82eb
commit d08cd36527
3 changed files with 34 additions and 8 deletions

View File

@@ -19,14 +19,9 @@ module Streams
intake = mediamtx_intake_url(session)
output = "rtmp://a.rtmp.youtube.com/live2/#{session.stream_key}"
# YouTube richiede FLV H.264/AAC stabili; -c copy lascia spesso streamStatus=inactive.
pid = Process.spawn(
"ffmpeg", "-nostdin", "-hide_banner", "-loglevel", "warning",
"-rw_timeout", "15000000",
"-i", intake,
"-c", "copy",
"-f", "flv",
output,
%i[out err] => log_path,
*youtube_ffmpeg_args(intake, output, log_path),
pgroup: true
)
Process.detach(pid)
@@ -62,13 +57,33 @@ module Streams
return if running?(session.id)
last_restart = redis.get(restart_debounce_key(session.id)).to_i
return if last_restart.positive? && (Time.now.to_i - last_restart) < 20
start(session)
redis.set(restart_debounce_key(session.id), Time.now.to_i, ex: 300)
rescue Error => e
Rails.logger.warn("[YoutubeRelay] ensure_publishing session=#{session.id}: #{e.message}")
end
private
def youtube_ffmpeg_args(intake, output, log_path)
[
"ffmpeg", "-nostdin", "-hide_banner", "-loglevel", "warning",
"-fflags", "+genpts+discardcorrupt", "-use_wallclock_as_timestamps", "1",
"-rw_timeout", "15000000",
"-i", intake,
"-map", "0:v:0", "-map", "0:a:0",
"-c:v", "libx264", "-preset", "veryfast", "-tune", "zerolatency",
"-pix_fmt", "yuv420p", "-r", "30", "-g", "30", "-keyint_min", "30", "-sc_threshold", "0",
"-b:v", "4000k", "-maxrate", "4000k", "-bufsize", "8000k",
"-c:a", "aac", "-b:a", "128k", "-ar", "48000", "-ac", "1",
"-f", "flv", output,
%i[out err] => log_path
]
end
def schedule_youtube_activate(session)
return if session.youtube_broadcast_id.blank?
@@ -88,6 +103,10 @@ module Streams
@redis ||= Redis.new(url: ENV.fetch("REDIS_URL", "redis://localhost:6379/0"))
end
def restart_debounce_key(session_id)
format("youtube_relay:debounce:%s", session_id)
end
def store_pid(session_id, pid)
redis.set(format(REDIS_KEY, session_id), pid, ex: 48.hours.to_i)
end