options.go 2.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132
  1. package ffmpeg
  2. import (
  3. "context"
  4. "os/exec"
  5. "strings"
  6. )
  7. type ffmpegBuilder struct {
  8. binary string // ffmpeg binary path
  9. options map[string]string // global options
  10. inputs []*inputBuilder // input options
  11. outputs []*outputBuilder // output options
  12. }
  13. func newFFmpegBuilder() *ffmpegBuilder {
  14. return &ffmpegBuilder{
  15. binary: "ffmpeg",
  16. options: make(map[string]string),
  17. }
  18. }
  19. func (b *ffmpegBuilder) AddInput(src *inputBuilder) {
  20. b.inputs = append(b.inputs, src)
  21. }
  22. func (b *ffmpegBuilder) AddOutput(dst *outputBuilder) {
  23. b.outputs = append(b.outputs, dst)
  24. }
  25. func (b *ffmpegBuilder) SetBinary(bin string) {
  26. b.binary = bin
  27. }
  28. func (b *ffmpegBuilder) SetFlag(flag string) {
  29. b.options[flag] = ""
  30. }
  31. func (b *ffmpegBuilder) SetOption(name, value string) {
  32. b.options[name] = value
  33. }
  34. func (b *ffmpegBuilder) Args() (args []string) {
  35. for name, val := range b.options {
  36. args = append(args, "-"+name)
  37. if val != "" {
  38. args = append(args, val)
  39. }
  40. }
  41. for _, input := range b.inputs {
  42. args = append(args, input.Args()...)
  43. }
  44. for _, output := range b.outputs {
  45. args = append(args, output.Args()...)
  46. }
  47. return
  48. }
  49. func (b *ffmpegBuilder) Command(ctx context.Context) *exec.Cmd {
  50. bin := "ffmpeg"
  51. if b.binary != "" {
  52. bin = b.binary
  53. }
  54. return exec.CommandContext(ctx, bin, b.Args()...)
  55. }
  56. // inputBuilder is the builder for ffmpeg input options
  57. type inputBuilder struct {
  58. path string
  59. options map[string][]string
  60. }
  61. func newInputBuilder(path string) *inputBuilder {
  62. return &inputBuilder{
  63. path: path,
  64. options: make(map[string][]string),
  65. }
  66. }
  67. func (b *inputBuilder) AddOption(name, value string) {
  68. b.options[name] = append(b.options[name], value)
  69. }
  70. func (b *inputBuilder) Args() (args []string) {
  71. for name, values := range b.options {
  72. for _, val := range values {
  73. args = append(args, "-"+name, val)
  74. }
  75. }
  76. return append(args, "-i", b.path)
  77. }
  78. // outputBuilder is the builder for ffmpeg output options
  79. type outputBuilder struct {
  80. path string
  81. options map[string][]string
  82. }
  83. func newOutputBuilder(path string) *outputBuilder {
  84. return &outputBuilder{
  85. path: path,
  86. options: make(map[string][]string),
  87. }
  88. }
  89. func (b *outputBuilder) AddOption(name, value string) {
  90. b.options[name] = append(b.options[name], value)
  91. }
  92. func (b *outputBuilder) Args() (args []string) {
  93. for name, values := range b.options {
  94. for _, val := range values {
  95. args = append(args, "-"+name, val)
  96. }
  97. }
  98. return append(args, b.path)
  99. }
  100. // AddMetadata is the shortcut for adding "metadata" option
  101. func (b *outputBuilder) AddMetadata(stream, key, value string) {
  102. optVal := strings.TrimSpace(key) + "=" + strings.TrimSpace(value)
  103. if stream != "" {
  104. b.AddOption("metadata:"+stream, optVal)
  105. } else {
  106. b.AddOption("metadata", optVal)
  107. }
  108. }