package services import ( "fmt" "sort" "strings" ) // HLSPlaylistGenerator génère des playlists HLS au format standard // T0341: Create HLS Master Playlist Generator type HLSPlaylistGenerator struct{} // NewHLSPlaylistGenerator crée un nouveau générateur de playlist HLS func NewHLSPlaylistGenerator() *HLSPlaylistGenerator { return &HLSPlaylistGenerator{} } // GenerateMasterPlaylist génère un master playlist HLS avec les variantes de qualité // bitrates: liste des bitrates en kbps (ex: [128, 192, 320]) // baseURL: URL de base pour les playlists de qualité (ex: "track_123" ou "http://example.com/track_123") // Retourne le contenu du master playlist au format HLS standard func (g *HLSPlaylistGenerator) GenerateMasterPlaylist(bitrates []int, baseURL string) string { var builder strings.Builder // En-tête HLS standard builder.WriteString("#EXTM3U\n") builder.WriteString("#EXT-X-VERSION:3\n") // Trier les bitrates par ordre croissant pour un meilleur streaming adaptatif sortedBitrates := make([]int, len(bitrates)) copy(sortedBitrates, bitrates) sort.Ints(sortedBitrates) // Générer une entrée pour chaque qualité for _, bitrate := range sortedBitrates { // Calculer la bandwidth en bits par seconde (bitrate est en kbps) bandwidth := bitrate * 1000 // Format HLS standard: #EXT-X-STREAM-INF:BANDWIDTH={bandwidth} // Pour l'audio, on peut aussi ajouter CODECS si nécessaire builder.WriteString(fmt.Sprintf("#EXT-X-STREAM-INF:BANDWIDTH=%d\n", bandwidth)) // URL relative vers le playlist de qualité // Format: {baseURL}/{bitrate}k/playlist.m3u8 builder.WriteString(fmt.Sprintf("%s/%dk/playlist.m3u8\n", baseURL, bitrate)) } return builder.String() } // GenerateMasterPlaylistWithCodecs génère un master playlist HLS avec codecs spécifiés // bitrates: liste des bitrates en kbps // baseURL: URL de base pour les playlists de qualité // codec: codec audio (ex: "mp4a.40.2" pour AAC-LC) // Retourne le contenu du master playlist avec codecs func (g *HLSPlaylistGenerator) GenerateMasterPlaylistWithCodecs(bitrates []int, baseURL string, codec string) string { var builder strings.Builder // En-tête HLS standard builder.WriteString("#EXTM3U\n") builder.WriteString("#EXT-X-VERSION:3\n") // Trier les bitrates par ordre croissant sortedBitrates := make([]int, len(bitrates)) copy(sortedBitrates, bitrates) sort.Ints(sortedBitrates) // Générer une entrée pour chaque qualité avec codec for _, bitrate := range sortedBitrates { bandwidth := bitrate * 1000 // Format HLS avec codec: #EXT-X-STREAM-INF:BANDWIDTH={bandwidth},CODECS="{codec}" builder.WriteString(fmt.Sprintf("#EXT-X-STREAM-INF:BANDWIDTH=%d,CODECS=\"%s\"\n", bandwidth, codec)) // URL relative vers le playlist de qualité builder.WriteString(fmt.Sprintf("%s/%dk/playlist.m3u8\n", baseURL, bitrate)) } return builder.String() } // GenerateQualityPlaylist génère une quality playlist HLS pour une qualité spécifique // T0342: Create HLS Quality Playlist Generator // segments: liste des noms de fichiers de segments (ex: ["segment_000.ts", "segment_001.ts"]) // segmentDuration: durée de chaque segment en secondes (ex: 10.0) // Retourne le contenu de la quality playlist au format HLS standard func (g *HLSPlaylistGenerator) GenerateQualityPlaylist(segments []string, segmentDuration float64) string { var builder strings.Builder // En-tête HLS standard builder.WriteString("#EXTM3U\n") builder.WriteString("#EXT-X-VERSION:3\n") // TARGETDURATION: durée maximale d'un segment (arrondie à l'entier supérieur) // Format: #EXT-X-TARGETDURATION:{duration} targetDuration := int(segmentDuration) if segmentDuration > float64(targetDuration) { targetDuration++ } builder.WriteString(fmt.Sprintf("#EXT-X-TARGETDURATION:%d\n", targetDuration)) // MEDIA-SEQUENCE: numéro de séquence du premier segment (0 pour VOD) builder.WriteString("#EXT-X-MEDIA-SEQUENCE:0\n") // PLAYLIST-TYPE: VOD (Video On Demand) pour les playlists complètes builder.WriteString("#EXT-X-PLAYLIST-TYPE:VOD\n") builder.WriteString("\n") // Ajouter chaque segment avec sa durée for _, segment := range segments { // Format: #EXTINF:{duration}, // La durée est en secondes avec 2 décimales builder.WriteString(fmt.Sprintf("#EXTINF:%.2f,\n", segmentDuration)) // Nom du fichier segment builder.WriteString(segment + "\n") } // Marqueur de fin pour les playlists VOD builder.WriteString("#EXT-X-ENDLIST\n") return builder.String() } // GenerateQualityPlaylistWithVariableDurations génère une quality playlist avec durées variables par segment // segments: liste des segments avec leurs durées respectives // Retourne le contenu de la quality playlist au format HLS standard func (g *HLSPlaylistGenerator) GenerateQualityPlaylistWithVariableDurations(segments []SegmentInfo) string { if len(segments) == 0 { return "#EXTM3U\n#EXT-X-VERSION:3\n#EXT-X-ENDLIST\n" } var builder strings.Builder // En-tête HLS standard builder.WriteString("#EXTM3U\n") builder.WriteString("#EXT-X-VERSION:3\n") // Calculer la durée maximale pour TARGETDURATION maxDuration := 0.0 for _, seg := range segments { if seg.Duration > maxDuration { maxDuration = seg.Duration } } targetDuration := int(maxDuration) if maxDuration > float64(targetDuration) { targetDuration++ } builder.WriteString(fmt.Sprintf("#EXT-X-TARGETDURATION:%d\n", targetDuration)) // MEDIA-SEQUENCE: numéro de séquence du premier segment builder.WriteString("#EXT-X-MEDIA-SEQUENCE:0\n") // PLAYLIST-TYPE: VOD builder.WriteString("#EXT-X-PLAYLIST-TYPE:VOD\n") builder.WriteString("\n") // Ajouter chaque segment avec sa durée spécifique for _, seg := range segments { builder.WriteString(fmt.Sprintf("#EXTINF:%.2f,\n", seg.Duration)) builder.WriteString(seg.Filename + "\n") } // Marqueur de fin builder.WriteString("#EXT-X-ENDLIST\n") return builder.String() } // SegmentInfo représente un segment avec sa durée type SegmentInfo struct { Filename string Duration float64 }