cursed mjpeg livestreaming
This commit is contained in:
parent
98311e3edf
commit
82f1b575f1
2 changed files with 31 additions and 1 deletions
|
@ -1,6 +1,10 @@
|
||||||
package http
|
package http
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
"time"
|
||||||
|
"mime/multipart"
|
||||||
|
"net/textproto"
|
||||||
|
"strconv"
|
||||||
"net/http"
|
"net/http"
|
||||||
"strings"
|
"strings"
|
||||||
"os"
|
"os"
|
||||||
|
@ -21,6 +25,7 @@ func server_setup(server *http.ServeMux) {
|
||||||
server.HandleFunc("/list/", serve_live_playlist) // uri returns the playlist file for the given stream key
|
server.HandleFunc("/list/", serve_live_playlist) // uri returns the playlist file for the given stream key
|
||||||
server.Handle("/static/", http.StripPrefix("/static/", http.FileServer(http.Dir("static/")))) // returns static files (eventually for the local hls player implementation)
|
server.Handle("/static/", http.StripPrefix("/static/", http.FileServer(http.Dir("static/")))) // returns static files (eventually for the local hls player implementation)
|
||||||
server.HandleFunc("/vid/", serve_vid_segment) // serves the appropriate static video segment
|
server.HandleFunc("/vid/", serve_vid_segment) // serves the appropriate static video segment
|
||||||
|
server.HandleFunc("/img/", serve_img_loop)
|
||||||
}
|
}
|
||||||
|
|
||||||
func serve_vid_segment(w http.ResponseWriter, r *http.Request) {
|
func serve_vid_segment(w http.ResponseWriter, r *http.Request) {
|
||||||
|
@ -50,3 +55,27 @@ func serve_main_page(w http.ResponseWriter, r *http.Request) {
|
||||||
stream_user := strings.TrimPrefix(r.URL.Path, "/live/")
|
stream_user := strings.TrimPrefix(r.URL.Path, "/live/")
|
||||||
page.Execute(w, stream_user) // literally only to define the uri for playlist loading, should be a script but eh
|
page.Execute(w, stream_user) // literally only to define the uri for playlist loading, should be a script but eh
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func serve_img_loop(w http.ResponseWriter, r *http.Request) {
|
||||||
|
w.Header().Set("Cache-Control", "no-cache")
|
||||||
|
stream_id := strings.TrimPrefix(r.URL.Path, "/img/")
|
||||||
|
base_dir, _ := os.UserHomeDir()
|
||||||
|
img_path := base_dir + "/live/" + stream_id + "/out.jpg"
|
||||||
|
|
||||||
|
writer := multipart.NewWriter(w)
|
||||||
|
w.Header().Set("Content-Type", "multipart/x-mixed-replace; boundary=" + writer.Boundary())
|
||||||
|
for {
|
||||||
|
img, err := os.ReadFile(img_path)
|
||||||
|
if err != nil {
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
part, err := writer.CreatePart(textproto.MIMEHeader{"Content-Type": {"image/jpeg"}, "Content-Length": {strconv.Itoa(len(img))}})
|
||||||
|
if err != nil {
|
||||||
|
break
|
||||||
|
}
|
||||||
|
part.Write(img)
|
||||||
|
time.Sleep(33 * time.Millisecond)
|
||||||
|
}
|
||||||
|
writer.Close()
|
||||||
|
|
||||||
|
}
|
||||||
|
|
|
@ -1,10 +1,11 @@
|
||||||
<!DOCTYPE html>
|
<!DOCTYPE html>
|
||||||
<html>
|
<html>
|
||||||
<head>
|
<head>
|
||||||
<title>Test</title>
|
<title>{{ . }}</title>
|
||||||
</head>
|
</head>
|
||||||
<body>
|
<body>
|
||||||
<video id=vid1 autoplay muted></video>
|
<video id=vid1 autoplay muted></video>
|
||||||
|
<img src="/img/{{ . }}"></img>
|
||||||
</body>
|
</body>
|
||||||
<script src="/static/hls-player.js"></script>
|
<script src="/static/hls-player.js"></script>
|
||||||
<script>var stream = new VideoLoader('vid1');</script>
|
<script>var stream = new VideoLoader('vid1');</script>
|
||||||
|
|
Loading…
Reference in a new issue