]> Zhao Yanbai Git Server - acecode.git/commitdiff
add audio player web
authorAceVest <zhaoyanbai@126.com>
Sun, 17 Jan 2021 14:29:31 +0000 (22:29 +0800)
committerAceVest <zhaoyanbai@126.com>
Sun, 17 Jan 2021 14:29:31 +0000 (22:29 +0800)
projects/audio_stream/audioweb/canvas.html [deleted file]
projects/audio_stream/audioweb/main.go
projects/audio_stream/audioweb/player.html [new file with mode: 0644]

diff --git a/projects/audio_stream/audioweb/canvas.html b/projects/audio_stream/audioweb/canvas.html
deleted file mode 100644 (file)
index 06d1810..0000000
+++ /dev/null
@@ -1,92 +0,0 @@
-<!DOCTYPE html>
-<html lang="en" dir="ltr">
-
-<head>
-    <meta charset="utf-8">
-    <title>CANVAS VIDEO</title>
-    <style>
-        #Video {
-            border: 1px solid red;
-        }
-    </style>
-</head>
-
-<body>
-    <canvas id="Video" width="120" height="160"></canvas>
-    <pre id="Stat"></pre>
-    <pre id="Msg"></pre>
-
-    <script>
-        var ws;
-        var wsURL = "ws://127.0.0.1/stream";
-        var canvas = document.getElementById('Video');
-        var ctx = canvas.getContext('2d'); 
-
-        var frameCount = 0;
-        var totalBytes = 0;
-        window.setInterval(function() {
-            fps = frameCount;
-            bytes = totalBytes;
-
-            frameCount = 0;
-            totalBytes = 0;
-            
-            var Stat = document.getElementById('Stat');
-            Stat.innerHTML = "当前帧率: " + fps + " fps, 带宽:" + (bytes*8.0/(1024.0*1024.0)).toFixed(1) + " Mbps";
-        },1000)
-
-        function Msg(...args) {
-            msg = args.join('');
-            console.log(msg);
-
-            var Msg = document.getElementById('Msg');
-            contents = Msg.innerHTML;
-            contents += msg;
-            slice = contents.split('\n').slice(-5);
-            msg = slice.join('\n')+'\n';
-            Msg.innerHTML = msg;
-        }
-    
-        function initWebsocket() {
-            ws = new WebSocket(wsURL);
-            ws.SendCmd = function(req) {
-                req = JSON.stringify(req);
-                ws.send(req);
-            }
-    
-            ws.onopen = function () {
-                Msg("websocket opened");
-            };
-    
-            ws.onerror = function (event) {
-                Msg("websocket error: " + event);
-            };
-    
-            ws.onclose = function (event) {
-                Msg("websocket closed with code: " + event.code + " reason: " + event.reason);
-            };
-    
-            ws.onmessage = function (event) {
-                imageData = event.data;
-                frameCount++;
-                totalBytes += imageData.size;
-                Msg("frame data len: ", imageData.size);
-                var image = new Image();
-                image.src = URL.createObjectURL(imageData);
-                image.onload = () => {
-                    URL.revokeObjectURL(image.src);
-                    ctx.save();
-                    ctx.translate(60, 80);
-                    ctx.rotate(90*(Math.PI/180));
-                    ctx.translate(-80, -60);
-                    ctx.drawImage(image, 0, 0);
-                    ctx.restore();
-                }
-            };
-        }
-
-        initWebsocket();
-    </script>
-</body>
-
-</html>
index e0ece94ea5605c034214102b415d1cfd6dda4edd..4c4cec5884e8cdd5b453a70cb00931bb80a68bab 100644 (file)
@@ -32,40 +32,9 @@ var upgrader = websocket.Upgrader{
 var frameChan chan []byte
 
 func init() {
-       frameChan = make(chan []byte, 8)
+       frameChan = make(chan []byte, 128)
 }
 
-const (
-       partBOUNDARY      = "123456789000000000000987654321"
-       streamContentType = "multipart/x-mixed-replace;boundary=" + partBOUNDARY
-       streamBoundary    = "\r\n--" + partBOUNDARY + "\r\n"
-       streamPart        = "Content-Type: image/jpeg\r\nContent-Length: %d\r\n\r\n"
-)
-
-func watchHandler(w http.ResponseWriter, r *http.Request) {
-       var err error
-       w.Header().Set("Content-Type", streamContentType)
-       w.Header().Set("Access-Control-Allow-Origin", "*")
-
-       flusher, _ := w.(http.Flusher)
-
-       for i := 0; ; i++ {
-               var data []byte
-               select {
-               case data = <-frameChan:
-                       fmt.Fprintf(w, "%v", streamBoundary)
-                       fmt.Fprintf(w, streamPart, i)
-                       _, err = w.Write(data)
-                       flusher.Flush()
-                       if err != nil {
-                               break
-                       }
-               default:
-                       continue
-               }
-
-       }
-}
 
 func audioHandler(w http.ResponseWriter, r *http.Request) {
        var err error
@@ -151,8 +120,8 @@ func streamHandler(w http.ResponseWriter, r *http.Request) {
        }
 }
 
-func canvasHandler(w http.ResponseWriter, r *http.Request) {
-       tmpl := template.Must(template.ParseFiles("./canvas.html"))
+func playerHandler(w http.ResponseWriter, r *http.Request) {
+       tmpl := template.Must(template.ParseFiles("./player.html"))
        var data = map[string]interface{}{}
        tmpl.Execute(w, data)
 }
@@ -161,9 +130,8 @@ func main() {
        defer fmt.Println("Program Exited...")
 
        m := http.NewServeMux()
-       m.HandleFunc("/watch", watchHandler)
        m.HandleFunc("/audio", audioHandler)
-       m.HandleFunc("/canvas", canvasHandler)
+       m.HandleFunc("/player", playerHandler)
        m.HandleFunc("/stream", streamHandler)
        server := http.Server{
                Addr:    ":80",
diff --git a/projects/audio_stream/audioweb/player.html b/projects/audio_stream/audioweb/player.html
new file mode 100644 (file)
index 0000000..0f5ec59
--- /dev/null
@@ -0,0 +1,140 @@
+<!DOCTYPE html>
+<html lang="en" dir="ltr">
+
+<head>
+    <meta charset="utf-8">
+    <title>AUDIO PLAYER</title>
+    <style>
+
+    </style>
+</head>
+
+<body>
+    <button onclick="play();">PLAY</button>
+    <pre id="Stat"></pre>
+    <pre id="Msg"></pre>
+
+    <script>
+        var ws;
+        var wsURL = "ws://10.0.0.6/stream";
+
+        var frameCount = 0;
+        var totalBytes = 0;
+        window.setInterval(function() {
+            fps = frameCount;
+            bytes = totalBytes;
+
+            frameCount = 0;
+            totalBytes = 0;
+
+            var Stat = document.getElementById('Stat');
+            Stat.innerHTML = "当前帧率: " + fps + " fps, 带宽:" + (bytes*8.0/(1024.0*1024.0)).toFixed(1) + " Mbps";
+        },1000)
+
+        function Msg(...args) {
+            msg = args.join('');
+            console.log(msg);
+
+            var Msg = document.getElementById('Msg');
+            contents = Msg.innerHTML;
+            contents += msg;
+            slice = contents.split('\n').slice(-5);
+            msg = slice.join('\n')+'\n';
+            Msg.innerHTML = msg;
+        }
+
+        class PcmDataPlayer {
+          constructor() {
+              this.sampleRate = 8000;
+              this.flushTime = 1000;
+              this.audioSamples = new Float32Array();
+
+              this.audioCtx = new window.AudioContext();
+              this.gainNode = this.audioCtx.createGain();
+              this.gainNode.connect(this.audioCtx.destination);
+              this.startTime = this.audioCtx.currentTime;
+
+              setInterval(this.play.bind(this), this.flushTime);
+          }
+          play() {
+            const length = this.audioSamples.length;
+
+            if (0 == length) {
+              return
+            }
+
+            const audioBuffer = this.audioCtx.createBuffer(1, length, this.sampleRate);
+            const audioData = audioBuffer.getChannelData(0);
+            for (let i = 0; i < length; i++) {
+              audioData[i] = this.audioSamples[i];
+            }
+
+            if (this.startTime < this.audioCtx.currentTime) {
+              this.startTime = this.audioCtx.currentTime;
+            }
+            console.log('start vs current ' + this.startTime.toFixed(2) + ' vs ' + this.audioCtx.currentTime.toFixed(2) + ' duration: ' + audioBuffer.duration.toFixed(2));
+
+            var bufferSource = this.audioCtx.createBufferSource();
+            bufferSource.buffer = audioBuffer;
+            bufferSource.connect(this.gainNode);
+            bufferSource.start(this.startTime);
+            this.startTime += audioBuffer.duration;
+            this.audioSamples = new Float32Array();
+          }
+
+          putAudioData(data) {
+            let float32Data = new Float32Array(data.length);
+            for (let i = 0; i < data.length; i++) {
+              float32Data[i] = data[i] / (32768.0/5.0);
+            }
+
+            const tmp = new Float32Array(this.audioSamples.length + float32Data.length);
+            tmp.set(this.audioSamples, 0);
+            tmp.set(float32Data,       this.audioSamples.length);
+            this.audioSamples = tmp;
+          }
+        }
+
+        // play函数会初始化音频设备
+        // 浏览器要求必需要用户手动触发,不能自动播放
+        // 因此该函数通过网页上的按钮click调用,而不是网页加载完成后直接调用
+        function play() {
+          var player = new PcmDataPlayer();
+
+          function initWebsocket() {
+              ws = new WebSocket(wsURL);
+              ws.binaryType = 'arraybuffer';
+              ws.SendCmd = function(req) {
+                  req = JSON.stringify(req);
+                  ws.send(req);
+              }
+
+              ws.onopen = function () {
+                  Msg("websocket opened");
+              };
+
+              ws.onerror = function (event) {
+                  Msg("websocket error: " + event);
+              };
+
+              ws.onclose = function (event) {
+                  Msg("websocket closed with code: " + event.code + " reason: " + event.reason);
+              };
+
+              ws.onmessage = function (event) {
+                  data = event.data;
+                  frameCount++;
+                  totalBytes += data.byteLength;
+
+                  data = Array.prototype.slice.call(new Uint16Array(data));
+                  player.putAudioData(data);
+              };
+          }
+
+          initWebsocket();
+        }
+
+    </script>
+</body>
+
+</html>