1. 程式人生 > >視訊彈幕帶時間同步demo

視訊彈幕帶時間同步demo

婚慶現場或年會上有在大屏上一直滾動的視訊,來賓關注公眾號後就可以直接傳送留言上牆了,看起來貌似好好玩的樣子
彈幕一般利用websocket和後臺server建立連線然後傳送/接收資料,這裡使用H5來做前臺頁面,只是一個demo沒有做過多的美化和優化,特別是server端程式碼,一旦資訊多了會撐爆記憶體,如果需要在實際中使用還需進一步處理。
前臺展示主要用到了websocket,基本上看原始碼就能明白,核心程式碼如下:

<script>
    //WebSocket
    var wsServer = 'ws://172.17.154.228:7181';
    var websocket=
new WebSocket(wsServer); websocket.onopen = function (evt) { console.log("Connected to WebSocket server."); /*websocket.send("gaga");*/ //連上之後就開啟彈幕 $('#danmu').danmu('danmuResume'); }; websocket.onclose = function (evt) { console.log("Disconnected")
; }; websocket.onmessage = function (evt) { console.log('Retrieved data from server: ' + evt.data); var time = $('#danmu').data("nowTime")+1; var text_obj = evt.data.indexOf("time") == -1 ? evt.data + ',"time":' + time + '}' : evt.data;//獲取加上當前時間 console.log(text_obj)
; var new_obj = eval('(' + text_obj + ')'); $('#danmu').danmu("addDanmu",new_obj);//新增彈幕 }; websocket.onerror = function (evt, e) { console.log('Error occured: ' + evt.data); }; //初始化 $("#danmu").danmu({ left:0, top:0, height:"100%", width:"100%", speed:20000, opacity:1, font_size_small:16, font_size_big:24, top_botton_danmu_time:6000 }); //一個定時器,監視彈幕時間並更新到頁面上 function timedCount(){ $("#time").text($('#danmu').data("nowTime")); t=setTimeout("timedCount()",50) } timedCount(); function starter(){ $('#danmu').danmu('danmuStart'); } function pauser(){ $('#danmu').danmu('danmuPause'); } function resumer(){ $('#danmu').danmu('danmuResume'); } function stoper(){ $('#danmu').danmu('danmuStop'); } function getime(){ alert($('#danmu').data("nowTime")); } function getpaused(){ alert($('#danmu').data("paused")); } //傳送彈幕,使用了文件README.md第7節中推薦的方法 function send(){ var text = document.getElementById('text').value; var color = document.getElementById('color').value; var position = document.getElementById('position').value; var time = $('#danmu').data("nowTime")+1; var size =document.getElementById('text_size').value; var text_obj='{ "text":"'+text+'","color":"'+color+'","size":"'+size+'","position":"'+position+'","time":'+time+'}'; //為了處理簡單,方便後續加time,和isnew,就先醬紫發一半吧。 //注:time為彈幕出來的時間,isnew為是否加邊框,自己發的彈幕,常理上來說是有邊框的。 //var text_obj='{ "text":"'+text+'","color":"'+color+'","size":"'+size+'","position":"'+position+'"'; //利用websocket傳送 websocket.send(text_obj); //清空相應的內容 document.getElementById('text').value=''; } //調整透明度函式 function op(){ var op=document.getElementById('op').value; $('#danmu').danmu("setOpacity",op/100); } //調隱藏 顯示 function changehide() { var op = document.getElementById('op').value; op = op / 100; if (document.getElementById("ishide").checked) { $("#danmu").danmu("setOpacity",1) } else { $("#danmu").danmu("setOpacity",0) } } //設定彈幕時間 function settime(){ var t=document.getElementById("set_time").value; t=parseInt(t) $('#danmu').danmu("setTime",t); } </script>

在服務端儲存每個進來的連線,然後將接收到的訊息分發出去

server.Start(socket =>
{
    socket.OnOpen = () =>
    {
        Console.WriteLine("Open!");
        foreach(string msg in readBuffer)
        {
            socket.Send(msg);
        }
        allSockets.Add(socket);
    };
    socket.OnClose = () =>
    {
        Console.WriteLine("Close!");
        allSockets.Remove(socket);
        if (allSockets.Count == 0)
        {
            StreamWriter sw = new StreamWriter(recordPath);
            foreach (string msg in readBuffer)
                sw.WriteLine(msg);
            sw.Close();
        }
    };
    socket.OnMessage = message =>
    {
        Console.WriteLine(message);
        readBuffer.Add(message);
        allSockets.ToList().ForEach(s => s.Send(message.Substring(0,message.LastIndexOf(','))));                    
    };
    socket.OnBinary = file => {
        string path = ("D:\\test.txt");
        //建立一個檔案流
        FileStream fs = new FileStream(path, FileMode.Create);
        //將byte陣列寫入檔案中
        fs.Write(file, 0, file.Length);        
        fs.Close();
    };
});


var input = Console.ReadLine();
while (input != "exit")
{
    foreach (var socket in allSockets.ToList())
    {
        socket.Send(input);
    }
    input = Console.ReadLine();
}

附加:原始碼傳送門