up
This commit is contained in:
parent
7f332aa88b
commit
b1866a2cc5
@ -228,6 +228,7 @@ func RoutesProtected(r *mux.Router, bd *gorm.DB) {
|
||||
r.HandleFunc("/api/paths/{id:[0-9]+}/media", renders.PathMedia(bd)).Methods("GET")
|
||||
r.HandleFunc("/stream/{partID:[0-9]+}", renders.Stream(bd)).Methods("GET")
|
||||
r.HandleFunc("/media/{partID:[0-9]+}", renders.MediaDetail(bd)).Methods("GET")
|
||||
r.HandleFunc("/hls/{partID:[0-9]+}/{file}", renders.HLSStream(bd)).Methods("GET")
|
||||
|
||||
//API Scan folder
|
||||
|
||||
|
||||
@ -985,7 +985,7 @@ type mediaDetailView struct {
|
||||
Summary string
|
||||
DurationFmt string
|
||||
ThumbURL string
|
||||
StreamURL string
|
||||
HLSURL string // ajouté
|
||||
}
|
||||
|
||||
// MediaDetail affiche la page détail + player
|
||||
@ -1024,7 +1024,7 @@ func MediaDetail(db *gorm.DB) http.HandlerFunc {
|
||||
Summary: item.Summary,
|
||||
DurationFmt: strconv.FormatInt(m, 10) + ":" + fmt.Sprintf("%02d", s),
|
||||
ThumbURL: item.UserThumbURL,
|
||||
StreamURL: "/stream/" + strconv.FormatInt(item.MediaPartID, 10),
|
||||
HLSURL: fmt.Sprintf("/hls/%d/index.m3u8", partID),
|
||||
}
|
||||
|
||||
} else {
|
||||
@ -1098,6 +1098,49 @@ func Stream(db *gorm.DB) http.HandlerFunc {
|
||||
}
|
||||
}
|
||||
|
||||
// renders/media.go (ajoutez cette fonction)
|
||||
func HLSStream(db *gorm.DB) http.HandlerFunc {
|
||||
return func(w http.ResponseWriter, r *http.Request) {
|
||||
// 1) identifier le média
|
||||
partID, _ := strconv.ParseInt(mux.Vars(r)["partID"], 10, 64)
|
||||
var part models.MediaPart
|
||||
if err := db.First(&part, partID).Error; err != nil {
|
||||
http.Error(w, "Média introuvable", http.StatusNotFound)
|
||||
return
|
||||
}
|
||||
|
||||
// 2) dossier temporaire / cache
|
||||
tmpDir := filepath.Join(os.TempDir(), fmt.Sprintf("hls_%d", partID))
|
||||
os.MkdirAll(tmpDir, 0755)
|
||||
playlist := filepath.Join(tmpDir, "index.m3u8")
|
||||
|
||||
// 3) si besoin, (re)générer l’HLS via ffmpeg
|
||||
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(),
|
||||
"ffmpeg",
|
||||
"-i", part.File,
|
||||
"-c:v", "copy", "-c:a", "copy",
|
||||
"-f", "hls",
|
||||
"-hls_time", "4",
|
||||
"-hls_list_size", "0",
|
||||
"-hls_segment_filename", filepath.Join(tmpDir, "seg%d.ts"),
|
||||
playlist,
|
||||
)
|
||||
if out, err := cmd.CombinedOutput(); err != nil {
|
||||
log.Println("ffmpeg HLS error:", err, string(out))
|
||||
http.Error(w, "Erreur de transcodage", 500)
|
||||
return
|
||||
}
|
||||
}
|
||||
|
||||
// 4) servir le dossier HLS en statique
|
||||
http.StripPrefix(
|
||||
fmt.Sprintf("/hls/%d/", partID),
|
||||
http.FileServer(http.Dir(tmpDir)),
|
||||
).ServeHTTP(w, r)
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
@ -1,14 +1,39 @@
|
||||
<div class="detail p-4">
|
||||
<h1 class="text-2xl font-bold mb-4">{{.item.Title}}</h1>
|
||||
{{with .item.Summary}}
|
||||
<p class="mb-4">{{.}}</p>
|
||||
{{end}}
|
||||
{{with .item.DurationFmt}}
|
||||
<small class="text-gray-500">{{.}}</small>
|
||||
{{end}}
|
||||
{{with .item.Summary}}<p class="mb-4">{{.}}</p>{{end}}
|
||||
{{with .item.DurationFmt}}<small class="text-gray-500">{{.}}</small>{{end}}
|
||||
<img src="{{.item.ThumbURL}}" alt="{{.item.Title}}" class="cover mb-4 rounded shadow" />
|
||||
<video controls autoplay width="100%" class="rounded shadow">
|
||||
<source src="{{.item.StreamURL}}" type="video/mp4">
|
||||
Votre navigateur ne supporte pas la vidéo.
|
||||
</video>
|
||||
|
||||
<!-- 1) Le bouton Play -->
|
||||
<button
|
||||
id="play-btn"
|
||||
class="px-4 py-2 bg-blue-600 text-white rounded hover:bg-blue-700"
|
||||
>▶ Play</button>
|
||||
|
||||
<!-- 2) Container vide pour le player -->
|
||||
<div id="player-container" class="mt-4"></div>
|
||||
|
||||
<script src="https://unpkg.com/hls.js@1.4.0"></script>
|
||||
<script>
|
||||
document.getElementById('play-btn').addEventListener('click', function(){
|
||||
const url = "{{.item.HLSURL}}";
|
||||
const container = document.getElementById('player-container');
|
||||
// injecte la balise video
|
||||
container.innerHTML = '<video id="video-player" controls autoplay width="100%" class="rounded shadow"></video>';
|
||||
const video = document.getElementById('video-player');
|
||||
|
||||
// si hls.js est supporté, on l’utilise
|
||||
if (Hls.isSupported()) {
|
||||
const hls = new Hls();
|
||||
hls.loadSource(url);
|
||||
hls.attachMedia(video);
|
||||
} else {
|
||||
// sinon on pose directement la source (Chrome & Safari gèrent nativement HLS)
|
||||
video.src = url;
|
||||
}
|
||||
|
||||
// cache le bouton
|
||||
this.style.display = 'none';
|
||||
});
|
||||
</script>
|
||||
</div>
|
||||
|
||||
Loading…
Reference in New Issue
Block a user