streamOutputVariant.go 2.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106
  1. package models
  2. import (
  3. "encoding/json"
  4. "fmt"
  5. "math"
  6. )
  7. // StreamOutputVariant defines the output specifics of a single HLS stream variant.
  8. type StreamOutputVariant struct {
  9. // Name is an optional human-readable label for this stream output.
  10. Name string `json:"name"`
  11. // Enable passthrough to copy the video and/or audio directly from the
  12. // incoming stream and disable any transcoding. It will ignore any of
  13. // the below settings.
  14. IsVideoPassthrough bool `yaml:"videoPassthrough" json:"videoPassthrough"`
  15. IsAudioPassthrough bool `yaml:"audioPassthrough" json:"audioPassthrough"`
  16. VideoBitrate int `yaml:"videoBitrate" json:"videoBitrate"`
  17. AudioBitrate int `yaml:"audioBitrate" json:"audioBitrate"`
  18. // Set only one of these in order to keep your current aspect ratio.
  19. // Or set neither to not scale the video.
  20. ScaledWidth int `yaml:"scaledWidth" json:"scaledWidth,omitempty"`
  21. ScaledHeight int `yaml:"scaledHeight" json:"scaledHeight,omitempty"`
  22. Framerate int `yaml:"framerate" json:"framerate"`
  23. // CPUUsageLevel represents a codec preset to configure CPU usage.
  24. CPUUsageLevel int `json:"cpuUsageLevel"`
  25. }
  26. // GetFramerate returns the framerate or default.
  27. func (q *StreamOutputVariant) GetFramerate() int {
  28. if q.IsVideoPassthrough {
  29. return 0
  30. }
  31. if q.Framerate > 0 {
  32. return q.Framerate
  33. }
  34. return 24
  35. }
  36. // GetIsAudioPassthrough will return if this variant audio is passthrough.
  37. func (q *StreamOutputVariant) GetIsAudioPassthrough() bool {
  38. if q.IsAudioPassthrough {
  39. return true
  40. }
  41. if q.AudioBitrate == 0 {
  42. return true
  43. }
  44. return false
  45. }
  46. // GetName will return the human readable name for this stream output.
  47. func (q *StreamOutputVariant) GetName() string {
  48. bitrate := getBitrateString(q.VideoBitrate)
  49. if q.Name != "" {
  50. return q.Name
  51. } else if q.IsVideoPassthrough {
  52. return "Source"
  53. } else if q.ScaledHeight == 720 && q.ScaledWidth == 1080 {
  54. return fmt.Sprintf("720p @%s", bitrate)
  55. } else if q.ScaledHeight == 1080 && q.ScaledWidth == 1920 {
  56. return fmt.Sprintf("1080p @%s", bitrate)
  57. } else if q.ScaledHeight != 0 {
  58. return fmt.Sprintf("%dh", q.ScaledHeight)
  59. } else if q.ScaledWidth != 0 {
  60. return fmt.Sprintf("%dw", q.ScaledWidth)
  61. } else {
  62. return fmt.Sprintf("%s@%dfps", bitrate, q.Framerate)
  63. }
  64. }
  65. func getBitrateString(bitrate int) string {
  66. if bitrate == 0 {
  67. return ""
  68. } else if bitrate < 1000 {
  69. return fmt.Sprintf("%dKbps", bitrate)
  70. } else if bitrate >= 1000 {
  71. if math.Mod(float64(bitrate), 1000) == 0 {
  72. return fmt.Sprintf("%dMbps", bitrate/1000.0)
  73. }
  74. return fmt.Sprintf("%.1fMbps", float32(bitrate)/1000.0)
  75. }
  76. return ""
  77. }
  78. // MarshalJSON is a custom JSON marshal function for video stream qualities.
  79. func (q *StreamOutputVariant) MarshalJSON() ([]byte, error) {
  80. type Alias StreamOutputVariant
  81. return json.Marshal(&struct {
  82. *Alias
  83. Framerate int `json:"framerate"`
  84. }{
  85. Framerate: q.GetFramerate(),
  86. Alias: (*Alias)(q),
  87. })
  88. }