veza/veza-backend-api/internal/services/bitrate_strategy_service.go
2025-12-03 20:29:37 +01:00

144 lines
5.1 KiB
Go

package services
import (
"go.uber.org/zap"
)
// BitrateStrategy représente une stratégie d'adaptation de bitrate
// T0361: Create Bitrate Adaptation Strategy Service
type BitrateStrategy string
const (
// StrategyConservative est une stratégie conservatrice qui adapte le bitrate
// seulement quand les conditions sont vraiment défavorables
StrategyConservative BitrateStrategy = "conservative"
// StrategyAggressive est une stratégie agressive qui adapte le bitrate
// rapidement pour éviter les problèmes de streaming
StrategyAggressive BitrateStrategy = "aggressive"
// StrategyBalanced est une stratégie équilibrée entre conservative et aggressive
StrategyBalanced BitrateStrategy = "balanced"
)
// StrategyThresholds représente les seuils pour une stratégie
type StrategyThresholds struct {
BufferLevelThreshold float64 // Seuil de niveau de buffer (0.0 à 1.0)
BandwidthRatioThreshold float64 // Seuil de ratio de bande passante (0.0 à 1.0)
UseOrCondition bool // Si true, utilise OR au lieu de AND
}
// BitrateStrategyService gère les stratégies d'adaptation de bitrate
type BitrateStrategyService struct {
logger *zap.Logger
}
// NewBitrateStrategyService crée un nouveau service de stratégies d'adaptation
func NewBitrateStrategyService(logger *zap.Logger) *BitrateStrategyService {
if logger == nil {
logger = zap.NewNop()
}
return &BitrateStrategyService{
logger: logger,
}
}
// GetThresholds retourne les seuils pour une stratégie donnée
func (s *BitrateStrategyService) GetThresholds(strategy BitrateStrategy) StrategyThresholds {
switch strategy {
case StrategyConservative:
// Conservative: adapte seulement si buffer ET bande passante sont faibles
return StrategyThresholds{
BufferLevelThreshold: 0.3, // 30% de buffer
BandwidthRatioThreshold: 0.7, // 70% de la bande passante nécessaire
UseOrCondition: false, // Utilise AND
}
case StrategyAggressive:
// Aggressive: adapte si buffer OU bande passante est faible
return StrategyThresholds{
BufferLevelThreshold: 0.15, // 15% de buffer
BandwidthRatioThreshold: 0.5, // 50% de la bande passante nécessaire
UseOrCondition: true, // Utilise OR
}
case StrategyBalanced:
fallthrough
default:
// Balanced: adapte si buffer ET bande passante sont modérément faibles
return StrategyThresholds{
BufferLevelThreshold: 0.2, // 20% de buffer
BandwidthRatioThreshold: 0.6, // 60% de la bande passante nécessaire
UseOrCondition: false, // Utilise AND
}
}
}
// ShouldAdapt détermine si une adaptation de bitrate est nécessaire
// selon la stratégie, le niveau de buffer et le ratio de bande passante
// bufferLevel: niveau de buffer (0.0 = vide, 1.0 = plein)
// bandwidthRatio: ratio de bande passante disponible / nécessaire (0.0 à 1.0+)
// Retourne true si une adaptation est nécessaire
func (s *BitrateStrategyService) ShouldAdapt(strategy BitrateStrategy, bufferLevel float64, bandwidthRatio float64) bool {
thresholds := s.GetThresholds(strategy)
// Valider les paramètres
if bufferLevel < 0 || bufferLevel > 1 {
s.logger.Warn("Invalid buffer level",
zap.Float64("buffer_level", bufferLevel),
zap.String("strategy", string(strategy)))
return false
}
if bandwidthRatio < 0 {
s.logger.Warn("Invalid bandwidth ratio",
zap.Float64("bandwidth_ratio", bandwidthRatio),
zap.String("strategy", string(strategy)))
return false
}
// Vérifier si le buffer est faible
bufferLow := bufferLevel < thresholds.BufferLevelThreshold
// Vérifier si la bande passante est faible
// bandwidthRatio < threshold signifie que la bande passante disponible
// est inférieure au seuil requis
bandwidthLow := bandwidthRatio < thresholds.BandwidthRatioThreshold
// Appliquer la logique selon la stratégie
if thresholds.UseOrCondition {
// OR: adapter si buffer OU bande passante est faible
return bufferLow || bandwidthLow
} else {
// AND: adapter seulement si buffer ET bande passante sont faibles
return bufferLow && bandwidthLow
}
}
// SelectStrategy sélectionne une stratégie selon le contexte
// networkStability: stabilité du réseau (0.0 = instable, 1.0 = stable)
// userPreference: préférence de l'utilisateur (peut être nil pour auto)
// Retourne la stratégie recommandée
func (s *BitrateStrategyService) SelectStrategy(networkStability float64, userPreference *BitrateStrategy) BitrateStrategy {
// Si l'utilisateur a une préférence, l'utiliser
if userPreference != nil {
return *userPreference
}
// Sélectionner automatiquement selon la stabilité du réseau
if networkStability < 0.3 {
// Réseau instable: utiliser une stratégie conservative
return StrategyConservative
} else if networkStability > 0.7 {
// Réseau stable: utiliser une stratégie aggressive pour meilleure qualité
return StrategyAggressive
} else {
// Réseau modéré: utiliser une stratégie balanced
return StrategyBalanced
}
}
// IsValidStrategy vérifie si une stratégie est valide
func (s *BitrateStrategyService) IsValidStrategy(strategy BitrateStrategy) bool {
return strategy == StrategyConservative ||
strategy == StrategyAggressive ||
strategy == StrategyBalanced
}