up
This commit is contained in:
parent
aa2433bee8
commit
12e9c11536
@ -1057,7 +1057,7 @@ func MediaDetail(db *gorm.DB) http.HandlerFunc {
|
|||||||
DurationFmt: "", // on ne probe pas ici
|
DurationFmt: "", // on ne probe pas ici
|
||||||
ThumbURL: "/static/thumbs/" + base + ".jpg",
|
ThumbURL: "/static/thumbs/" + base + ".jpg",
|
||||||
// on passe le path en query pour le streaming
|
// on passe le path en query pour le streaming
|
||||||
HLSURL: fmt.Sprintf("/hls/%d/index.m3u8", partID),
|
HLSURL: "/hls/0/index.m3u8?path=" + url.QueryEscape(path),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1101,25 +1101,38 @@ func Stream(db *gorm.DB) http.HandlerFunc {
|
|||||||
// renders/media.go (ajoutez cette fonction)
|
// renders/media.go (ajoutez cette fonction)
|
||||||
func HLSStream(db *gorm.DB) http.HandlerFunc {
|
func HLSStream(db *gorm.DB) http.HandlerFunc {
|
||||||
return func(w http.ResponseWriter, r *http.Request) {
|
return func(w http.ResponseWriter, r *http.Request) {
|
||||||
// 1) identifier le média
|
vars := mux.Vars(r)
|
||||||
partID, _ := strconv.ParseInt(mux.Vars(r)["partID"], 10, 64)
|
partID, _ := strconv.ParseInt(vars["partID"], 10, 64)
|
||||||
|
|
||||||
|
// Déterminer le fichier source
|
||||||
|
var filePath string
|
||||||
|
if partID > 0 {
|
||||||
|
// cas BDD
|
||||||
var part models.MediaPart
|
var part models.MediaPart
|
||||||
if err := db.First(&part, partID).Error; err != nil {
|
if err := db.First(&part, partID).Error; err != nil {
|
||||||
http.Error(w, "Média introuvable", http.StatusNotFound)
|
http.Error(w, "Média introuvable", http.StatusNotFound)
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
filePath = part.File
|
||||||
|
} else {
|
||||||
|
// cas FS-only
|
||||||
|
filePath = r.URL.Query().Get("path")
|
||||||
|
if filePath == "" {
|
||||||
|
http.Error(w, "Média introuvable", http.StatusNotFound)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// 2) dossier temporaire / cache
|
// Préparer le dossier de cache HLS
|
||||||
tmpDir := filepath.Join(os.TempDir(), fmt.Sprintf("hls_%d", partID))
|
tmpDir := filepath.Join(os.TempDir(), fmt.Sprintf("hls_%d", partID))
|
||||||
os.MkdirAll(tmpDir, 0755)
|
os.MkdirAll(tmpDir, 0755)
|
||||||
playlist := filepath.Join(tmpDir, "index.m3u8")
|
playlist := filepath.Join(tmpDir, "index.m3u8")
|
||||||
|
|
||||||
// 3) si besoin, (re)générer l’HLS via ffmpeg
|
// (Re)générer si nécessaire
|
||||||
if _, err := os.Stat(playlist); os.IsNotExist(err) {
|
if _, err := os.Stat(playlist); os.IsNotExist(err) {
|
||||||
// ffmpeg -i input -c:v copy -c:a copy -f hls -hls_time 4 -hls_list_size 0 tmp/index.m3u8
|
|
||||||
cmd := exec.CommandContext(r.Context(),
|
cmd := exec.CommandContext(r.Context(),
|
||||||
"ffmpeg",
|
"ffmpeg",
|
||||||
"-i", part.File,
|
"-i", filePath,
|
||||||
"-c:v", "copy", "-c:a", "copy",
|
"-c:v", "copy", "-c:a", "copy",
|
||||||
"-f", "hls",
|
"-f", "hls",
|
||||||
"-hls_time", "4",
|
"-hls_time", "4",
|
||||||
@ -1129,14 +1142,14 @@ func HLSStream(db *gorm.DB) http.HandlerFunc {
|
|||||||
)
|
)
|
||||||
if out, err := cmd.CombinedOutput(); err != nil {
|
if out, err := cmd.CombinedOutput(); err != nil {
|
||||||
log.Println("ffmpeg HLS error:", err, string(out))
|
log.Println("ffmpeg HLS error:", err, string(out))
|
||||||
http.Error(w, "Erreur de transcodage", 500)
|
http.Error(w, "Erreur de transcodage", http.StatusInternalServerError)
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// 4) servir le dossier HLS en statique
|
// Servir le dossier HLS
|
||||||
http.StripPrefix(
|
prefix := fmt.Sprintf("/hls/%d/", partID)
|
||||||
fmt.Sprintf("/hls/%d/", partID),
|
http.StripPrefix(prefix,
|
||||||
http.FileServer(http.Dir(tmpDir)),
|
http.FileServer(http.Dir(tmpDir)),
|
||||||
).ServeHTTP(w, r)
|
).ServeHTTP(w, r)
|
||||||
}
|
}
|
||||||
@ -1145,6 +1158,7 @@ func HLSStream(db *gorm.DB) http.HandlerFunc {
|
|||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
func renderPartial(w http.ResponseWriter, templ string, data map[string]interface{}) {
|
func renderPartial(w http.ResponseWriter, templ string, data map[string]interface{}) {
|
||||||
// Exécute directement le define `<templ>.pages.tmpl`
|
// Exécute directement le define `<templ>.pages.tmpl`
|
||||||
if err := templates.ExecuteTemplate(w, templ+".pages.tmpl", data); err != nil {
|
if err := templates.ExecuteTemplate(w, templ+".pages.tmpl", data); err != nil {
|
||||||
|
|||||||
Loading…
Reference in New Issue
Block a user