135 lines
3.8 KiB
Go
135 lines
3.8 KiB
Go
package handlers
|
|
|
|
import (
|
|
"net/http"
|
|
|
|
"github.com/google/uuid"
|
|
|
|
// "strconv" // Removed this import
|
|
|
|
"veza-backend-api/internal/services"
|
|
|
|
"github.com/gin-gonic/gin"
|
|
)
|
|
|
|
// HLSHandler gère les requêtes pour servir les fichiers HLS
|
|
type HLSHandler struct {
|
|
hlsService *services.HLSService
|
|
}
|
|
|
|
// NewHLSHandler crée un nouveau handler HLS
|
|
func NewHLSHandler(hlsService *services.HLSService) *HLSHandler {
|
|
return &HLSHandler{hlsService: hlsService}
|
|
}
|
|
|
|
// ServeMasterPlaylist sert le master playlist pour un track
|
|
func (h *HLSHandler) ServeMasterPlaylist(c *gin.Context) {
|
|
trackID, err := uuid.Parse(c.Param("id")) // Changed to uuid.Parse
|
|
if err != nil {
|
|
c.JSON(http.StatusBadRequest, gin.H{"error": "invalid track id"})
|
|
return
|
|
}
|
|
|
|
playlist, err := h.hlsService.GetMasterPlaylist(c.Request.Context(), trackID)
|
|
if err != nil {
|
|
c.JSON(http.StatusNotFound, gin.H{"error": "playlist not found"})
|
|
return
|
|
}
|
|
|
|
c.Header("Content-Type", "application/vnd.apple.mpegurl")
|
|
c.Header("Cache-Control", "no-cache")
|
|
c.String(http.StatusOK, playlist)
|
|
}
|
|
|
|
// ServeQualityPlaylist sert une quality playlist pour un track et bitrate
|
|
func (h *HLSHandler) ServeQualityPlaylist(c *gin.Context) {
|
|
trackID, err := uuid.Parse(c.Param("id")) // Changed to uuid.Parse
|
|
if err != nil {
|
|
c.JSON(http.StatusBadRequest, gin.H{"error": "invalid track id"})
|
|
return
|
|
}
|
|
|
|
bitrate := c.Param("bitrate")
|
|
playlist, err := h.hlsService.GetQualityPlaylist(c.Request.Context(), trackID, bitrate)
|
|
if err != nil {
|
|
c.JSON(http.StatusNotFound, gin.H{"error": "playlist not found"})
|
|
return
|
|
}
|
|
|
|
c.Header("Content-Type", "application/vnd.apple.mpegurl")
|
|
c.Header("Cache-Control", "no-cache")
|
|
c.String(http.StatusOK, playlist)
|
|
}
|
|
|
|
// ServeSegment sert un segment pour un track, bitrate et nom de segment
|
|
func (h *HLSHandler) ServeSegment(c *gin.Context) {
|
|
trackID, err := uuid.Parse(c.Param("id")) // Changed to uuid.Parse
|
|
if err != nil {
|
|
c.JSON(http.StatusBadRequest, gin.H{"error": "invalid track id"})
|
|
return
|
|
}
|
|
|
|
bitrate := c.Param("bitrate")
|
|
segment := c.Param("segment")
|
|
|
|
segmentPath, err := h.hlsService.GetSegmentPath(c.Request.Context(), trackID, bitrate, segment)
|
|
if err != nil {
|
|
c.JSON(http.StatusNotFound, gin.H{"error": "segment not found"})
|
|
return
|
|
}
|
|
|
|
c.Header("Content-Type", "video/mp2t")
|
|
c.Header("Cache-Control", "public, max-age=3600")
|
|
c.File(segmentPath)
|
|
}
|
|
|
|
// GetStreamStatus retourne le statut d'un stream HLS pour un track
|
|
func (h *HLSHandler) GetStreamStatus(c *gin.Context) {
|
|
trackID, err := uuid.Parse(c.Param("id")) // Changed to uuid.Parse
|
|
if err != nil {
|
|
c.JSON(http.StatusBadRequest, gin.H{"error": "invalid track id"})
|
|
return
|
|
}
|
|
|
|
status, err := h.hlsService.GetStreamStatus(c.Request.Context(), trackID)
|
|
if err != nil {
|
|
c.JSON(http.StatusNotFound, gin.H{"error": "stream not found"})
|
|
return
|
|
}
|
|
|
|
c.JSON(http.StatusOK, status)
|
|
}
|
|
|
|
// TriggerTranscode déclenche le transcodage HLS d'un track via la queue (T0343)
|
|
func (h *HLSHandler) TriggerTranscode(c *gin.Context) {
|
|
userID, ok := GetUserIDUUID(c)
|
|
if !ok {
|
|
return // Erreur déjà envoyée par GetUserIDUUID
|
|
}
|
|
if userID == uuid.Nil {
|
|
c.JSON(http.StatusUnauthorized, gin.H{"error": "unauthorized"})
|
|
return
|
|
}
|
|
|
|
trackID, err := uuid.Parse(c.Param("id")) // Changed to uuid.Parse
|
|
if err != nil {
|
|
c.JSON(http.StatusBadRequest, gin.H{"error": "invalid track id"})
|
|
return
|
|
}
|
|
|
|
jobID, err := h.hlsService.TriggerTranscodeQueue(c.Request.Context(), trackID, userID)
|
|
if err != nil {
|
|
if err.Error() == "track not found" {
|
|
c.JSON(http.StatusNotFound, gin.H{"error": "track not found"})
|
|
return
|
|
}
|
|
if err.Error() == "forbidden: user does not own this track" {
|
|
c.JSON(http.StatusForbidden, gin.H{"error": "forbidden"})
|
|
return
|
|
}
|
|
c.JSON(http.StatusInternalServerError, gin.H{"error": err.Error()})
|
|
return
|
|
}
|
|
|
|
c.JSON(http.StatusAccepted, gin.H{"job_id": jobID})
|
|
}
|