-
Notifications
You must be signed in to change notification settings - Fork 71
/
provider.go
194 lines (163 loc) · 6.02 KB
/
provider.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
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
package provider // import "github.com/video-dev/video-transcoding-api/provider"
import (
"errors"
"fmt"
"sort"
"time"
"github.com/video-dev/video-transcoding-api/config"
"github.com/video-dev/video-transcoding-api/db"
)
var (
// ErrProviderAlreadyRegistered is the error returned when trying to register a
// provider twice.
ErrProviderAlreadyRegistered = errors.New("provider is already registered")
// ErrProviderNotFound is the error returned when asking for a provider
// that is not registered.
ErrProviderNotFound = errors.New("provider not found")
// ErrPresetMapNotFound is the error returned when the given preset is not
// found in the provider.
ErrPresetMapNotFound = errors.New("preset not found in provider")
)
// TranscodingProvider represents a provider of transcoding.
//
// It defines a basic API for transcoding a media and query the status of a
// Job. The underlying provider should handle the profileSpec as desired (it
// might be a JSON, or an XML, or anything else.
type TranscodingProvider interface {
Transcode(*db.Job) (*JobStatus, error)
JobStatus(*db.Job) (*JobStatus, error)
CancelJob(id string) error
CreatePreset(db.Preset) (string, error)
DeletePreset(presetID string) error
GetPreset(presetID string) (interface{}, error)
// Healthcheck should return nil if the provider is currently available
// for transcoding videos, otherwise it should return an error
// explaining what's going on.
Healthcheck() error
// Capabilities describes the capabilities of the provider.
Capabilities() Capabilities
}
// Factory is the function responsible for creating the instance of a
// provider.
type Factory func(cfg *config.Config) (TranscodingProvider, error)
// InvalidConfigError is returned if a provider could not be configured properly
type InvalidConfigError string
// JobNotFoundError is returned if a job with a given id could not be found by the provider
type JobNotFoundError struct {
ID string
}
func (err InvalidConfigError) Error() string {
return string(err)
}
func (err JobNotFoundError) Error() string {
return fmt.Sprintf("could not found job with id: %s", err.ID)
}
// JobStatus is the representation of the status as the provide sees it. The
// provider is able to add customized information in the ProviderStatus field.
//
// swagger:model
type JobStatus struct {
ProviderJobID string `json:"providerJobId,omitempty"`
Status Status `json:"status,omitempty"`
ProviderName string `json:"providerName,omitempty"`
StatusMessage string `json:"statusMessage,omitempty"`
Progress float64 `json:"progress"`
ProviderStatus map[string]interface{} `json:"providerStatus,omitempty"`
Output JobOutput `json:"output"`
SourceInfo SourceInfo `json:"sourceInfo,omitempty"`
}
// JobOutput represents information about a job output.
type JobOutput struct {
Destination string `json:"destination,omitempty"`
Files []OutputFile `json:"files,omitempty"`
}
// OutputFile represents an output file in a given job.
type OutputFile struct {
Path string `json:"path"`
Container string `json:"container"`
VideoCodec string `json:"videoCodec"`
Height int64 `json:"height"`
Width int64 `json:"width"`
FileSize int64 `json:"fileSize"`
}
// SourceInfo contains information about media transcoded using the Transcoding
// API.
type SourceInfo struct {
// Duration of the media
Duration time.Duration `json:"duration,omitempty"`
// Dimension of the media, in pixels
Height int64 `json:"height,omitempty"`
Width int64 `json:"width,omitempty"`
// Codec used for video medias
VideoCodec string `json:"videoCodec,omitempty"`
}
// Status is the status of a transcoding job.
type Status string
const (
// StatusQueued is the status for a job that is in the queue for
// execution.
StatusQueued = Status("queued")
// StatusStarted is the status for a job that is being executed.
StatusStarted = Status("started")
// StatusFinished is the status for a job that finished successfully.
StatusFinished = Status("finished")
// StatusFailed is the status for a job that has failed.
StatusFailed = Status("failed")
// StatusCanceled is the status for a job that has been canceled.
StatusCanceled = Status("canceled")
// StatusUnknown is an unexpected status for a job.
StatusUnknown = Status("unknown")
)
var providers map[string]Factory
// Register register a new provider in the internal list of providers.
func Register(name string, provider Factory) error {
if providers == nil {
providers = make(map[string]Factory)
}
if _, ok := providers[name]; ok {
return ErrProviderAlreadyRegistered
}
providers[name] = provider
return nil
}
// GetProviderFactory looks up the list of registered providers and returns the
// factory function for the given provider name, if it's available.
func GetProviderFactory(name string) (Factory, error) {
factory, ok := providers[name]
if !ok {
return nil, ErrProviderNotFound
}
return factory, nil
}
// ListProviders returns the list of currently registered providers,
// alphabetically ordered.
func ListProviders(c *config.Config) []string {
providerNames := make([]string, 0, len(providers))
for name, factory := range providers {
if _, err := factory(c); err == nil {
providerNames = append(providerNames, name)
}
}
sort.Strings(providerNames)
return providerNames
}
// DescribeProvider describes the given provider. It includes information about
// the provider's capabilities and its current health state.
func DescribeProvider(name string, c *config.Config) (*Description, error) {
factory, err := GetProviderFactory(name)
if err != nil {
return nil, err
}
description := Description{Name: name}
provider, err := factory(c)
if err != nil {
return &description, nil
}
description.Enabled = true
description.Capabilities = provider.Capabilities()
description.Health = Health{OK: true}
if err = provider.Healthcheck(); err != nil {
description.Health = Health{OK: false, Message: err.Error()}
}
return &description, nil
}