livego icon indicating copy to clipboard operation
livego copied to clipboard

如何查询流是否已经可以被请求

Open cs246810 opened this issue 3 years ago • 1 comments

例如,首先使用ffmpeg发布流到livego服务器,然后这边浏览器请求流,问题出在后边,浏览器请求流,由于第一步发布流还没喂进去数据,浏览器就请求了,这时由于流没有发布,所以请求是跨域阻止的。对应的源代码如下:

func (server *Server) handleConn(w http.ResponseWriter, r *http.Request) {                                                                                             
     defer func() {                                                                                                                                                     
         if r := recover(); r != nil {                                                                                                                                  
             log.Error("http flv handleConn panic: ", r)                                                                                                                
         }                                                                                                                                                              
     }()                                                                                                                                                                
                                                                                                                                                                        
     url := r.URL.String()                                                                                                                                              
     u := r.URL.Path                                                                                                                                                    
     if pos := strings.LastIndex(u, "."); pos < 0 || u[pos:] != ".flv" {                                                                                                
         http.Error(w, "invalid path", http.StatusBadRequest)                                                                                                           
         return                                                                                                                                                         
     }                                                                                                                                                                  
     path := strings.TrimSuffix(strings.TrimLeft(u, "/"), ".flv")                                                                                                       
     paths := strings.SplitN(path, "/", 2)                                                                                                                              
     log.Debug("url:", u, "path:", path, "paths:", paths)                                                                                                               
                                                                                                                                                                        
     if len(paths) != 2 {                                                                                                                                               
         http.Error(w, "invalid path", http.StatusBadRequest)                                                                                                           
         return                                                                                                                                                         
     }                                                                                                                                                                  
                                                                                                                                                                        
     // 判断视屏流是否发布,如果没有发布,直接返回404                                                                                                                     
     msgs := server.getStreams(w, r)                                                                                                                                    
     if msgs == nil || len(msgs.Publishers) == 0 {                                                                                                                      
         http.Error(w, "invalid path", http.StatusNotFound)                                                                                                             
         return                                                                                                                                                         
     } else {                                                                                                                                                           
         include := false                                                                                                                                               
         for _, item := range msgs.Publishers {                                                                                                                         
             if item.Key == path {                                                                                                                                      
                 include = true                                                                                                                                         
                 break                                                                                                                                                  
             }                                                                                                                                                          
         }                                                                                                                                                              
         if include == false {                                                                                                                                          
             http.Error(w, "invalid path", http.StatusNotFound)                                                                                                         
             return                                                                                                                                                     
         }                                                                                                                                                              
     }                                                                                                                                                                  
                                                                                                                                                                        
     w.Header().Set("Access-Control-Allow-Origin", "*")                                                                                                                 
     writer := NewFLVWriter(paths[0], paths[1], url, w)                                                                                                                 
                                                                                                                                                                        
     server.handler.HandleWriter(writer)                                                                                                                                
     writer.Wait()                                                                                                                                                      
 }            

这里w.Header().Set("Access-Control-Allow-Origin", "*") 只会在最后设置跨域头,所以前面,如果流没发布,直接就浏览器跨域阻止了。

这里的代码,能不能弄一个单独查询流是否可以被播放的就绪接口:

// 判断视屏流是否发布,如果没有发布,直接返回404                                                                                                                     
     msgs := server.getStreams(w, r)                                                                                                                                    
     if msgs == nil || len(msgs.Publishers) == 0 {                                                                                                                      
         http.Error(w, "invalid path", http.StatusNotFound)                                                                                                             
         return                                                                                                                                                         
     } else {                                                                                                                                                           
         include := false                                                                                                                                               
         for _, item := range msgs.Publishers {                                                                                                                         
             if item.Key == path {                                                                                                                                      
                 include = true                                                                                                                                         
                 break                                                                                                                                                  
             }                                                                                                                                                          
         }                                                                                                                                                              
         if include == false {                                                                                                                                          
             http.Error(w, "invalid path", http.StatusNotFound)                                                                                                         
             return                                                                                                                                                     
         }                                                                                                                                                              
     }                     

这样请求flv直播的流程就变成了,首先推流,然后查询流是否可以被播放,最后就是播放。

这样的好处就是,可以不在播放时,由于流没有就绪(可以播放),所导致前面返回invalid path而没有设置跨域头引起的浏览器阻止而拦截请求的情况。这样,浏览器客户端js写代码之前,也可以setinternal来循环判断流的状态,从而恢复直播播放,因为流可能被中断,网络断开或者其它任何影响客户端连续播放的原因。

cs246810 avatar Aug 04 '21 03:08 cs246810

同问

clouddea avatar Nov 26 '23 09:11 clouddea