Files
MatchLiveTv/backend/app/services/youtube/broadcast_service.rb
Emiliano Frascaro 1677df7f86 Visibilità pubblico/link-only su tutte le piattaforme di streaming.
Default pubblico; opzione unica privato/non in elenco per Match Live TV,
YouTube piattaforma e canale società. Elenco dirette solo sessioni pubbliche.

Co-authored-by: Cursor <cursoragent@cursor.com>
2026-06-02 23:00:34 +02:00

99 lines
3.3 KiB
Ruby
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
module Youtube
class BroadcastService
class Error < StandardError; end
def initialize(team, youtube_channel: nil)
@team = team
@resolver = CredentialResolver.new(team, channel: youtube_channel)
@credential = @resolver.resolve
end
def create_broadcast!(title:, privacy_status: "public", scheduled_at: nil)
return mock_broadcast if @credential.blank? || missing_oauth_config?
client = authorized_client
broadcast = Google::Apis::YoutubeV3::LiveBroadcast.new(
snippet: Google::Apis::YoutubeV3::LiveBroadcastSnippet.new(
title: title,
scheduled_start_time: scheduled_at&.iso8601
),
status: Google::Apis::YoutubeV3::LiveBroadcastStatus.new(
privacy_status: privacy_status,
self_declared_made_for_kids: false
),
content_details: Google::Apis::YoutubeV3::LiveBroadcastContentDetails.new(
enable_auto_start: true,
enable_auto_stop: true
)
)
result = client.insert_live_broadcast("snippet,status,contentDetails", broadcast)
stream = Google::Apis::YoutubeV3::LiveStream.new(
snippet: Google::Apis::YoutubeV3::LiveStreamSnippet.new(title: "#{title} stream"),
cdn: Google::Apis::YoutubeV3::CdnSettings.new(
frame_rate: "30fps",
ingestion_type: "rtmp",
resolution: "720p"
)
)
stream_result = client.insert_live_stream("snippet,cdn", stream)
client.bind_live_broadcast(result.id, "id,contentDetails", stream_result.id)
{
broadcast_id: result.id,
stream_id: stream_result.id,
stream_key: stream_result.cdn.ingestion_info.stream_name,
rtmp_url: stream_result.cdn.ingestion_info.ingestion_address
}
rescue Google::Apis::Error => e
raise Error, friendly_api_error(e)
end
def complete_broadcast!(broadcast_id)
return if @credential.blank? || missing_oauth_config?
client = authorized_client
client.transition_live_broadcast(broadcast_id, "complete")
rescue Google::Apis::Error
nil
end
def viewer_count(broadcast_id)
return 0 if @credential.blank? || missing_oauth_config?
client = authorized_client
resp = client.list_live_broadcasts("statistics", id: broadcast_id)
resp.items&.first&.statistics&.concurrent_viewers.to_i
rescue Google::Apis::Error
0
end
private
def mock_broadcast
{
broadcast_id: "mock_#{SecureRandom.hex(8)}",
stream_id: "mock_stream",
stream_key: ENV.fetch("YOUTUBE_MOCK_STREAM_KEY", "mock-stream-key"),
rtmp_url: "rtmp://a.rtmp.youtube.com/live2"
}
end
def missing_oauth_config?
ENV["YOUTUBE_CLIENT_ID"].blank?
end
def authorized_client
OauthRefresh.new(@credential).apply!(Google::Apis::YoutubeV3::YouTubeService.new)
end
def friendly_api_error(error)
msg = error.message.to_s
return "Il canale YouTube non ha la diretta attiva. Apri YouTube Studio con laccount del canale Match Live TV, abilita la live (verifica telefono se richiesto) e riprova." if msg.include?("liveStreamingNotEnabled")
return "Credenziali YouTube non valide. Ricollega il canale dalla sezione Admin → YouTube." if msg.match?(/Unauthorized|invalid_grant/i)
msg
end
end
end