-
Notifications
You must be signed in to change notification settings - Fork 174
/
ffmpeg.go
166 lines (154 loc) · 5.09 KB
/
ffmpeg.go
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
package ffmpeg_go
import (
"context"
"errors"
"io"
"log"
"os"
"strings"
"github.com/aws/aws-sdk-go/aws"
"github.com/aws/aws-sdk-go/aws/session"
"github.com/aws/aws-sdk-go/service/s3/s3manager"
)
// Input file URL (ffmpeg “-i“ option)
//
// Any supplied kwargs are passed to ffmpeg verbatim (e.g. “t=20“,
// “f='mp4'“, “acodec='pcm'“, etc.).
//
// To tell ffmpeg to read from stdin, use “pipe:“ as the filename.
//
// Official documentation: `Main options <https://ffmpeg.org/ffmpeg.html#Main-options>`__
func Input(filename string, kwargs ...KwArgs) *Stream {
args := MergeKwArgs(kwargs)
args["filename"] = filename
if fmt := args.PopString("f"); fmt != "" {
if args.HasKey("format") {
panic(errors.New("can't specify both `format` and `f` options"))
}
args["format"] = fmt
}
return NewInputNode("input", nil, args).Stream("", "")
}
// Add extra global command-line argument(s), e.g. “-progress“.
func (s *Stream) GlobalArgs(args ...string) *Stream {
if s.Type != "OutputStream" {
panic("cannot overwrite outputs on non-OutputStream")
}
return NewGlobalNode("global_args", []*Stream{s}, args, nil).Stream("", "")
}
// Overwrite output files without asking (ffmpeg “-y“ option)
//
// Official documentation: `Main options <https://ffmpeg.org/ffmpeg.html#Main-options>`_
func (s *Stream) OverwriteOutput(stream *Stream) *Stream {
if s.Type != "OutputStream" {
panic("cannot overwrite outputs on non-OutputStream")
}
return NewGlobalNode("overwrite_output", []*Stream{stream}, []string{"-y"}, nil).Stream("", "")
}
// Include all given outputs in one ffmpeg command line
func MergeOutputs(streams ...*Stream) *Stream {
return NewMergeOutputsNode("merge_output", streams).Stream("", "")
}
// Output file URL
//
// Syntax:
// `ffmpeg.Output([]*Stream{stream1, stream2, stream3...}, filename, kwargs)`
//
// Any supplied keyword arguments are passed to ffmpeg verbatim (e.g.
// ``t=20``, ``f='mp4'``, ``acodec='pcm'``, ``vcodec='rawvideo'``,
// etc.). Some keyword-arguments are handled specially, as shown below.
//
// Args:
// video_bitrate: parameter for ``-b:v``, e.g. ``video_bitrate=1000``.
// audio_bitrate: parameter for ``-b:a``, e.g. ``audio_bitrate=200``.
// format: alias for ``-f`` parameter, e.g. ``format='mp4'``
// (equivalent to ``f='mp4'``).
//
// If multiple streams are provided, they are mapped to the same
// output.
//
// To tell ffmpeg to write to stdout, use ``pipe:`` as the filename.
//
// Official documentation: `Synopsis <https://ffmpeg.org/ffmpeg.html#Synopsis>`__
// """
func Output(streams []*Stream, fileName string, kwargs ...KwArgs) *Stream {
args := MergeKwArgs(kwargs)
if !args.HasKey("filename") {
if fileName == "" {
panic("filename must be provided")
}
args["filename"] = fileName
}
return NewOutputNode("output", streams, nil, args).Stream("", "")
}
// Output file URL
//
// Syntax:
// `ffmpeg.Output(ctx, []*Stream{stream1, stream2, stream3...}, filename, kwargs)`
//
// Any supplied keyword arguments are passed to ffmpeg verbatim (e.g.
// ``t=20``, ``f='mp4'``, ``acodec='pcm'``, ``vcodec='rawvideo'``,
// etc.). Some keyword-arguments are handled specially, as shown below.
//
// Args:
// video_bitrate: parameter for ``-b:v``, e.g. ``video_bitrate=1000``.
// audio_bitrate: parameter for ``-b:a``, e.g. ``audio_bitrate=200``.
// format: alias for ``-f`` parameter, e.g. ``format='mp4'``
// (equivalent to ``f='mp4'``).
//
// If multiple streams are provided, they are mapped to the same
// output.
//
// To tell ffmpeg to write to stdout, use ``pipe:`` as the filename.
//
// Official documentation: `Synopsis <https://ffmpeg.org/ffmpeg.html#Synopsis>`__
// """
func OutputContext(ctx context.Context, streams []*Stream, fileName string, kwargs ...KwArgs) *Stream {
output := Output(streams, fileName, kwargs...)
output.Context = ctx
return output
}
func (s *Stream) Output(fileName string, kwargs ...KwArgs) *Stream {
if s.Type != "FilterableStream" {
log.Panic("cannot output on non-FilterableStream")
}
if strings.HasPrefix(fileName, "s3://") {
return s.outputS3Stream(fileName, kwargs...)
}
return OutputContext(s.Context, []*Stream{s}, fileName, kwargs...)
}
func (s *Stream) outputS3Stream(fileName string, kwargs ...KwArgs) *Stream {
r, w := io.Pipe()
fileL := strings.SplitN(strings.TrimPrefix(fileName, "s3://"), "/", 2)
if len(fileL) != 2 {
log.Panic("s3 file format not valid")
}
args := MergeKwArgs(kwargs)
awsConfig := args.PopDefault("aws_config", &aws.Config{}).(*aws.Config)
bucket, key := fileL[0], fileL[1]
o := Output([]*Stream{s}, "pipe:", args).
WithOutput(w, os.Stdout)
done := make(chan struct{})
runHook := RunHook{
f: func() {
defer func() {
done <- struct{}{}
}()
sess, err := session.NewSession(awsConfig)
uploader := s3manager.NewUploader(sess)
_, err = uploader.Upload(&s3manager.UploadInput{
Bucket: &bucket,
Key: &key,
Body: r,
})
//fmt.Println(ioutil.ReadAll(r))
if err != nil {
log.Println("upload fail", err)
}
},
done: done,
closer: w,
}
o.Context = context.WithValue(o.Context, "run_hook", &runHook)
return o
}