Alleggerisce il relay YouTube e rilascia Android 2.0.8.
ffmpeg fa solo remux copy A/V; le app fissano AAC 48 kHz mono; sync deploy non cancella più garage.prod.toml. Co-authored-by: Cursor <cursoragent@cursor.com>
This commit is contained in:
@@ -20,8 +20,8 @@ android {
|
||||
applicationId = "com.matchlivetv.match_live_tv"
|
||||
minSdk = 24
|
||||
targetSdk = 36
|
||||
versionCode = 28
|
||||
versionName = "2.0.7-native"
|
||||
versionCode = 29
|
||||
versionName = "2.0.8-native"
|
||||
|
||||
val apiBaseUrl = project.findProperty("API_BASE_URL") as String?
|
||||
?: "https://www.matchlivetv.it"
|
||||
|
||||
+11
-1
@@ -1,5 +1,9 @@
|
||||
package com.matchlivetv.match_live_tv.streaming
|
||||
|
||||
/**
|
||||
* Profilo RTMP allineato a MediaMTX slate + relay YouTube (copy audio/video).
|
||||
* Audio: AAC 48 kHz mono 128 kbps — stesso contratto di `infra/scripts/generate_slate.sh`.
|
||||
*/
|
||||
data class BroadcastConfig(
|
||||
val rtmpUrl: String,
|
||||
val width: Int = 1280,
|
||||
@@ -11,7 +15,13 @@ data class BroadcastConfig(
|
||||
val portrait: Boolean = false,
|
||||
val maxReconnectAttempts: Int = 10,
|
||||
val reconnectDelayMs: Long = 5_000L,
|
||||
)
|
||||
) {
|
||||
companion object {
|
||||
const val AUDIO_SAMPLE_RATE_HZ = 48_000
|
||||
/** false = mono in RootEncoder `prepareAudio(sampleRate, isStereo, bitrate)`. */
|
||||
const val AUDIO_STEREO = false
|
||||
}
|
||||
}
|
||||
|
||||
enum class BroadcastPhase {
|
||||
IDLE,
|
||||
|
||||
+5
-1
@@ -316,7 +316,11 @@ class LiveBroadcastEngine(
|
||||
rotation = cfg.rotation,
|
||||
profile = MediaCodecInfo.CodecProfileLevel.AVCProfileBaseline,
|
||||
level = h264Level,
|
||||
) && stream.prepareAudio(48_000, false, cfg.audioBitrate)
|
||||
) && stream.prepareAudio(
|
||||
BroadcastConfig.AUDIO_SAMPLE_RATE_HZ,
|
||||
BroadcastConfig.AUDIO_STEREO,
|
||||
cfg.audioBitrate,
|
||||
)
|
||||
}.getOrElse {
|
||||
Log.w(TAG, "preparePipeline: ${it.message}")
|
||||
false
|
||||
|
||||
@@ -1,5 +1,7 @@
|
||||
import Foundation
|
||||
|
||||
/// Profilo RTMP allineato a MediaMTX slate + YoutubeRelay (copy A/V).
|
||||
/// Audio: AAC 48 kHz mono 128 kbps.
|
||||
struct BroadcastConfig: Sendable {
|
||||
let rtmpUrl: String
|
||||
var width: Int = 1280
|
||||
@@ -11,6 +13,9 @@ struct BroadcastConfig: Sendable {
|
||||
var portrait: Bool = false
|
||||
var maxReconnectAttempts: Int = 10
|
||||
var reconnectDelayMs: Int = 5_000
|
||||
|
||||
static let audioSampleRateHz: Float64 = 48_000
|
||||
static let audioChannels: UInt32 = 1
|
||||
}
|
||||
|
||||
enum BroadcastPhase: String, Sendable {
|
||||
|
||||
@@ -214,6 +214,14 @@ final class LiveBroadcastEngine: ObservableObject {
|
||||
if let microphone = AVCaptureDevice.default(for: .audio) {
|
||||
try await mixer.attachAudio(microphone, track: 0)
|
||||
}
|
||||
// AAC 48 kHz mono — allineato ad Android, slate MediaMTX e YoutubeRelay (-c:a copy).
|
||||
try await mixer.setAudioMixerSettings(
|
||||
AudioMixerSettings(
|
||||
sampleRate: BroadcastConfig.audioSampleRateHz,
|
||||
channels: BroadcastConfig.audioChannels,
|
||||
tracks: [0: AudioMixerTrackSettings(downmix: true, channelMap: [0])]
|
||||
)
|
||||
)
|
||||
if let camera = AVCaptureDevice.default(.builtInWideAngleCamera, for: .video, position: .back) {
|
||||
try await mixer.attachVideo(camera, track: 0) { videoUnit in
|
||||
videoUnit.isVideoMirrored = false
|
||||
@@ -355,10 +363,10 @@ final class LiveBroadcastEngine: ObservableObject {
|
||||
var audioSettings = await stream.audioSettings
|
||||
audioSettings = AudioCodecSettings(
|
||||
bitRate: config.audioBitrate,
|
||||
downmix: audioSettings.downmix,
|
||||
channelMap: audioSettings.channelMap,
|
||||
sampleRate: 48_000,
|
||||
format: audioSettings.format
|
||||
downmix: true,
|
||||
channelMap: [0],
|
||||
sampleRate: BroadcastConfig.audioSampleRateHz,
|
||||
format: .aac
|
||||
)
|
||||
try await stream.setAudioSettings(audioSettings)
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user