开发订阅者插件

所谓订阅者就是用来从流媒体服务器接收音视频流的程序,例如RTMP协议执行play命令后、http-flv请求响应程序、websocket响应程序。内置插件中录制flv程序也是一个特殊的订阅者。下面是http-flv插件的源码,供参考

  1. package HDL
  2. import (
  3. . "github.com/langhuihui/monibuca/monica"
  4. "github.com/langhuihui/monibuca/monica/avformat"
  5. "github.com/langhuihui/monibuca/monica/pool"
  6. "log"
  7. "net/http"
  8. "strings"
  9. )
  10. var config = new(ListenerConfig)
  11. func init() {
  12. InstallPlugin(&PluginConfig{
  13. Name: "HDL",
  14. Type: PLUGIN_SUBSCRIBER,
  15. Config: config,
  16. Run: run,
  17. })
  18. }
  19. func run() {
  20. log.Printf("HDL start at %s", config.ListenAddr)
  21. log.Fatal(http.ListenAndServe(config.ListenAddr, http.HandlerFunc(HDLHandler)))
  22. }
  23. func HDLHandler(w http.ResponseWriter, r *http.Request) {
  24. sign := r.URL.Query().Get("sign")
  25. if err := AuthHooks.Trigger(sign); err != nil {
  26. w.WriteHeader(403)
  27. return
  28. }
  29. stringPath := strings.TrimLeft(r.RequestURI, "/")
  30. if strings.HasSuffix(stringPath, ".flv") {
  31. stringPath = strings.TrimRight(stringPath, ".flv")
  32. }
  33. if _, ok := AllRoom.Load(stringPath); ok {
  34. //atomic.AddInt32(&hdlId, 1)
  35. w.Header().Set("Transfer-Encoding", "chunked")
  36. w.Header().Set("Content-Type", "video/x-flv")
  37. w.Write(avformat.FLVHeader)
  38. p := OutputStream{
  39. Sign: sign,
  40. SendHandler: func(packet *pool.SendPacket) error {
  41. return avformat.WriteFLVTag(w, packet)
  42. },
  43. SubscriberInfo: SubscriberInfo{
  44. ID: r.RemoteAddr, Type: "FLV",
  45. },
  46. }
  47. p.Play(stringPath)
  48. } else {
  49. w.WriteHeader(404)
  50. }
  51. }

其中,核心逻辑就是创建OutputStream对象,每一个订阅者需要提供SendHandler函数,用来接收来自发布者广播出来的音视频数据。最后调用该对象的Play函数进行播放。请注意:Play函数会阻塞当前goroutine。