dm_seg.go 3.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138
  1. package model
  2. import (
  3. "fmt"
  4. )
  5. var (
  6. // segmentLength 分段长度,根据视频时长做分段,单位:毫秒
  7. segmentLength = int64(6 * 60 * 1000)
  8. _defaultSeg = &Segment{Start: 0, End: DefaultVideoEnd, Cnt: 1, Num: 1, Duration: 0}
  9. // <d p="弹幕ID,弹幕属性,播放时间,弹幕模式,字体大小,颜色,发送时间,弹幕池,用户hash id">弹幕内容</d>
  10. _xmlSegFmt = `<d p="%d,%d,%d,%d,%d,%d,%d,%d,%s">%s</d>`
  11. // DefaultPage default page info
  12. DefaultPage = &Page{Num: 1, Size: DefaultVideoEnd, Total: 1}
  13. _xmlSegHeader = `<?xml version="1.0" encoding="UTF-8"?><i><oid>%d</oid><ps>%d</ps><pe>%d</pe><pc>%d</pc><pn>%d</pn><state>%d</state><real_name>%d</real_name>`
  14. )
  15. // const variable
  16. const (
  17. // DefaultVideoEnd 当视频时长不存在或者为0时的默认视频结尾时间点
  18. DefaultVideoEnd = 10 * 60 * 60 * 1000
  19. // DefaultPageSize 默认分段长度
  20. DefaultPageSize = 60 * 6 * 1000
  21. )
  22. // Page dm page info
  23. type Page struct {
  24. Num int64 `json:"num"`
  25. Size int64 `json:"size"`
  26. Total int64 `json:"total"`
  27. }
  28. // Segment dm segment struct
  29. type Segment struct {
  30. Start int64 `json:"ps"` // 分段起始时间
  31. End int64 `json:"pe"` // 分段结束时间
  32. Cnt int64 `json:"cnt"` // 总分段数
  33. Num int64 `json:"num"` // 当前第几段
  34. Duration int64 `json:"duration"` // 视频总时长
  35. }
  36. // ToXMLHeader convert segment to xml header format.
  37. func (s *Segment) ToXMLHeader(oid int64, state, realname int32) string {
  38. return fmt.Sprintf(_xmlSegHeader, oid, s.Start, s.End, s.Cnt, s.Num, state, realname)
  39. }
  40. // SegmentInfo get segment info by start time and video duration.
  41. func SegmentInfo(ps, duration int64) (s *Segment) {
  42. var cnt, num, pe int64
  43. if duration == 0 {
  44. s = _defaultSeg
  45. return
  46. }
  47. cnt = duration / DefaultPageSize
  48. if duration%DefaultPageSize > 0 {
  49. cnt++
  50. }
  51. for i := int64(0); i < cnt; i++ {
  52. if ps >= i*DefaultPageSize && ps < (i+1)*DefaultPageSize {
  53. ps = i * DefaultPageSize
  54. pe = (i + 1) * DefaultPageSize
  55. num = i + 1
  56. }
  57. }
  58. if pe > duration {
  59. pe = duration
  60. }
  61. s = &Segment{
  62. Start: ps,
  63. End: pe,
  64. Cnt: cnt,
  65. Num: num,
  66. Duration: duration,
  67. }
  68. return
  69. }
  70. // ToXMLSeg convert dm struct to xml.
  71. func (d *DM) ToXMLSeg() (s string) {
  72. if d.Content == nil {
  73. return
  74. }
  75. msg := d.Content.Msg
  76. if d.ContentSpe != nil {
  77. msg = d.ContentSpe.Msg
  78. }
  79. if len(msg) == 0 {
  80. return
  81. }
  82. if d.Pool == PoolSpecial {
  83. msg = ""
  84. }
  85. s = fmt.Sprintf(_xmlSegFmt, d.ID, d.Attr, d.Progress, d.Content.Mode, d.Content.FontSize, d.Content.Color, d.Ctime, d.Pool, hash(d.Mid, uint32(d.Content.IP)), xmlReplace([]byte(msg)))
  86. return
  87. }
  88. // ToElem convert dm struct to element.
  89. func (d *DM) ToElem() (e *Elem) {
  90. if d.Content == nil {
  91. return
  92. }
  93. msg := d.Content.Msg
  94. if d.ContentSpe != nil {
  95. msg = d.ContentSpe.Msg
  96. }
  97. if len(msg) == 0 {
  98. return
  99. }
  100. if d.Pool == PoolSpecial {
  101. msg = ""
  102. }
  103. // "弹幕ID,弹幕属性,播放时间,弹幕模式,字体大小,颜色,发送时间,弹幕池,用户hash id
  104. e = &Elem{
  105. Attribute: fmt.Sprintf(`%d,%d,%d,%d,%d,%d,%d,%d,%s`, d.ID, d.Attr, d.Progress, d.Content.Mode, d.Content.FontSize, d.Content.Color, d.Ctime, d.Pool, hash(d.Mid, uint32(d.Content.IP))),
  106. Content: msg,
  107. }
  108. return
  109. }
  110. // SegmentPoint 根据当前段数和视频总时长计算分段的起始时间点
  111. func SegmentPoint(num, duration int64) (ps, pe int64) {
  112. if duration == 0 {
  113. ps = 0
  114. pe = DefaultVideoEnd
  115. return
  116. }
  117. pe = num * segmentLength
  118. ps = pe - segmentLength
  119. if pe > duration {
  120. pe = duration
  121. }
  122. if ps < 0 {
  123. ps = 0
  124. }
  125. return
  126. }