Initial commit: monorepo Match Live TV.
Rails API, app Flutter, infrastruttura Docker/MediaMTX, sito marketing e documentazione di deploy. Co-authored-by: Cursor <cursoragent@cursor.com>
This commit is contained in:
61
backend/app/services/sessions/create.rb
Normal file
61
backend/app/services/sessions/create.rb
Normal file
@@ -0,0 +1,61 @@
|
||||
module Sessions
|
||||
class Create
|
||||
def initialize(user:, match:, params:)
|
||||
@user = user
|
||||
@match = match
|
||||
@params = params
|
||||
end
|
||||
|
||||
def call
|
||||
platform = @params[:platform].presence || "matchlivetv"
|
||||
ent = @match.team.entitlements
|
||||
ent.assert_can_stream_on!(platform)
|
||||
ent.assert_concurrent_stream!
|
||||
|
||||
session = StreamSession.new(
|
||||
match: @match,
|
||||
user: @user,
|
||||
platform: platform,
|
||||
privacy_status: @params[:privacy_status] || "unlisted",
|
||||
quality_preset: @params[:quality_preset] || "720p_30_2.5mbps",
|
||||
target_bitrate: @params[:target_bitrate] || 2_500_000,
|
||||
target_fps: @params[:target_fps] || 30,
|
||||
status: "idle"
|
||||
)
|
||||
|
||||
if session.platform == "youtube"
|
||||
attach_youtube_broadcast!(session)
|
||||
end
|
||||
|
||||
StreamSession.transaction do
|
||||
session.save!
|
||||
session.create_score_state!
|
||||
Mediamtx::Client.new.create_path(session)
|
||||
log_event(session, "pairing", { created: true, platform: session.platform })
|
||||
end
|
||||
|
||||
session
|
||||
end
|
||||
|
||||
private
|
||||
|
||||
def attach_youtube_broadcast!(session)
|
||||
yt = Youtube::BroadcastService.new(session.match.team)
|
||||
title = "#{session.match.team.name} vs #{session.match.opponent_name}"
|
||||
broadcast = yt.create_broadcast!(
|
||||
title: title,
|
||||
privacy_status: session.privacy_status,
|
||||
scheduled_at: session.match.scheduled_at
|
||||
)
|
||||
|
||||
session.youtube_broadcast_id = broadcast[:broadcast_id]
|
||||
session.youtube_stream_id = broadcast[:stream_id]
|
||||
session.stream_key = broadcast[:stream_key]
|
||||
session.rtmp_url = broadcast[:rtmp_url]
|
||||
end
|
||||
|
||||
def log_event(session, type, metadata)
|
||||
session.stream_events.create!(event_type: type, metadata: metadata, occurred_at: Time.current)
|
||||
end
|
||||
end
|
||||
end
|
||||
20
backend/app/services/sessions/pause.rb
Normal file
20
backend/app/services/sessions/pause.rb
Normal file
@@ -0,0 +1,20 @@
|
||||
module Sessions
|
||||
class Pause
|
||||
def initialize(session)
|
||||
@session = session
|
||||
end
|
||||
|
||||
def call
|
||||
@session.pause! if @session.may_pause?
|
||||
log_event("paused")
|
||||
SessionChannel.broadcast_message(@session, { type: "command", action: "pause_stream" })
|
||||
@session
|
||||
end
|
||||
|
||||
private
|
||||
|
||||
def log_event(type)
|
||||
@session.stream_events.create!(event_type: type, occurred_at: Time.current, metadata: {})
|
||||
end
|
||||
end
|
||||
end
|
||||
21
backend/app/services/sessions/start.rb
Normal file
21
backend/app/services/sessions/start.rb
Normal file
@@ -0,0 +1,21 @@
|
||||
module Sessions
|
||||
class Start
|
||||
def initialize(session)
|
||||
@session = session
|
||||
end
|
||||
|
||||
def call
|
||||
@session.match.team.entitlements.assert_concurrent_stream!(excluding_session: @session)
|
||||
@session.begin_connect! if @session.may_begin_connect?
|
||||
@session.update!(status: "connecting") unless @session.connecting?
|
||||
broadcast_status("connecting")
|
||||
@session
|
||||
end
|
||||
|
||||
private
|
||||
|
||||
def broadcast_status(status)
|
||||
SessionChannel.broadcast_message(@session, { type: "stream_event", event: "starting", status: status })
|
||||
end
|
||||
end
|
||||
end
|
||||
30
backend/app/services/sessions/stop.rb
Normal file
30
backend/app/services/sessions/stop.rb
Normal file
@@ -0,0 +1,30 @@
|
||||
module Sessions
|
||||
class Stop
|
||||
def initialize(session)
|
||||
@session = session
|
||||
end
|
||||
|
||||
def call
|
||||
cancel_timeout_job
|
||||
@session.end_stream!
|
||||
Youtube::BroadcastService.new(@session.match.team).complete_broadcast!(@session.youtube_broadcast_id)
|
||||
Recordings::IndexSession.new(@session).call
|
||||
Mediamtx::Client.new.delete_path(@session)
|
||||
log_event("ended")
|
||||
SessionChannel.broadcast_message(@session, { type: "stream_event", event: "ended" })
|
||||
@session
|
||||
end
|
||||
|
||||
private
|
||||
|
||||
def cancel_timeout_job
|
||||
return if @session.timeout_job_id.blank?
|
||||
|
||||
Sidekiq::ScheduledSet.new.find_job(@session.timeout_job_id)&.delete
|
||||
end
|
||||
|
||||
def log_event(type)
|
||||
@session.stream_events.create!(event_type: type, occurred_at: Time.current, metadata: {})
|
||||
end
|
||||
end
|
||||
end
|
||||
Reference in New Issue
Block a user