gwuhaolin / livego

live video streaming server in golang
MIT License
9.58k stars 1.99k forks source link

livego伺服器關閉前,推播儲存的flv檔,即使串流已停止也無法刪除 #140

Open KhaymanHung opened 3 years ago

KhaymanHung commented 3 years ago

然後同一個channel如果重新串流,神奇的事發生了 livego在接受到新的串流時,會建立新的flv檔儲存新的推播畫面 但如果這個channel在伺服器開啟後有串流過,新的推播畫面,不但會儲存在新的flv檔內,連舊的flv檔也會繼續儲存… 重覆停止串流、開始串流的動作後,每一個之前串流的影片都會繼續儲存新的推播畫面 也就是同個channel第二次串流時,消耗的硬碟空間會變成兩倍…第三次就變成三倍… 這大概是flv檔沒有在串流中斷後關閉造成的

KhaymanHung commented 3 years ago

查了一下,stream.go的closeInter func裡的s.ws.Delete(key),不知道為什麼沒有把WriteCloser從那個map裡移除 開debug後,delete下面那一行debug訊息有出現,但在range完後再range一次查看map時發現WriteCloser還在

matthewgao commented 3 years ago

听起来有点说不通,是否有看到 ”http flv closed“ 这个日志,理论上就算map中的WriteCloser,flvwriter如果已经closed 也不会写两份

KhaymanHung commented 3 years ago

這我真的不知道為什麼,因為實際上後面再用range列舉一次後,應該被delete的key的確還存在 如果我在後面的range中不分青紅皂白的把所有key都delete的話,倒是的確可以delete掉,但在同時有兩個以上來源的推流時就會出問題了

TOBEMINE commented 3 years ago

测试了一下 确实存在livego不关闭 存储的flv文件 即使推流关闭也不能删除的情况 是操作文件的io 在停止推流没有关闭吧

TOBEMINE commented 3 years ago

查了一下,stream.go的closeInter func裡的s.ws.Delete(key),不知道為什麼沒有把WriteCloser從那個map裡移除 開debug後,delete下面那一行debug訊息有出現,但在range完後再range一次查看map時發現WriteCloser還在

closeInter func裡的s.ws.Delete(key) 的上一句 v.w.Close(fmt.Errorf("closed")) 是不是没执行

KhaymanHung commented 3 years ago

closeInter func裡的s.ws.Delete(key) 的上一句 v.w.Close(fmt.Errorf("closed")) 是不是没执行

似乎是沒有,因為我試過在flvwriter的close裡加上log,可是log訊息沒有出現 但是那個if裡面最後那一行log訊息是有的,理論上來說,前面的v.w.Close(fmt.Errorf("closed"))和s.ws.Delete(key)這兩行應該也有跑到才對…

KhaymanHung commented 3 years ago

closeInter func裡的s.ws.Delete(key) 的上一句 v.w.Close(fmt.Errorf("closed")) 是不是没执行

似乎是沒有,因為我試過在flvwriter的close裡加上log,可是log訊息沒有出現 但是那個if裡面最後那一行log訊息是有的,理論上來說,前面的v.w.Close(fmt.Errorf("closed"))和s.ws.Delete(key)這兩行應該也有跑到才對…

我追了一下確定了一件事,其實delete和close都有做,但問題是每次串流時,map中會儲存兩個writecloser,一個會在v.w.Info().IsInterval()判斷中關閉和刪除的,應該是推播時會用到的,另一個推流存檔的影片檔案用的,而這個在串流中斷時並沒有被close和delete,結果就是同一個channel再過來時,畫面存檔就會連這個一起存下去了 可是這個卻又不能直接delete掉,我試過在clostInter時不判斷IsInterval就把整個map清空,只有一個串流來源時還好,有多個串流來源時就會出問題…雖然我不知道為什麼,因為不同channel應該是不同Stream才對… anyway,雖然不知道為什麼會這樣,但既然會如此那就不要delete,只是單純close似乎就沒問題了,所以我把那段變成了這樣 s.ws.Range(func(key, val interface{}) bool { v := val.(*PackWriterCloser) if v.w != nil { v.w.Close(fmt.Errorf("closed")) if v.w.Info().IsInterval() { s.ws.Delete(key) log.Debugf("[%v] player closed and remove\n", v.w.Info()) } } return true })