-
Notifications
You must be signed in to change notification settings - Fork 71
proposal: add new refactored bitmovin provider using new sdk #210
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Conversation
Codecov Report
@@ Coverage Diff @@
## master #210 +/- ##
=======================================
Coverage 78.62% 78.62%
=======================================
Files 29 29
Lines 2914 2914
=======================================
Hits 2291 2291
Misses 372 372
Partials 251 251 Continue to review full report at Codecov.
|
There is currently one known issue with the new SDK, filed here: bitmovin/bitmovin-api-sdk-go#1 |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Overall all the object usage looks correct
@@ -7,6 +7,7 @@ import ( | |||
"github.com/NYTimes/gizmo/server" | |||
"github.com/NYTimes/video-transcoding-api/config" | |||
_ "github.com/NYTimes/video-transcoding-api/provider/bitmovin" | |||
_ "github.com/NYTimes/video-transcoding-api/provider/bitmovinnewsdk" |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Would perhaps suggest using bitmovinopenapi
if a new provider name is required
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
yup, makes sense, the name I chose was meant to be a placeholder until there was clarity on if this replaced the current provider or will be available in addition to it
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Is this using a different API or just a different SDK?
If it's a different SDK or a new API that's already GA, let's have this replace the old provider 😁
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
It's the same API, but a new SDK (although the SDK is still in alpha)
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
That should be fine, let's do it! 😬
if err != nil { | ||
return model.H264VideoConfiguration{}, err | ||
} | ||
cfg.MaxGop = gopSize // TODO: investigate this to ensure it respects preset gop mode and size |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
MaxGop
is correct to use when defining the GOP in frames
vodHLSManifests = []model.ManifestResource{{ManifestId: manifestID}} | ||
} | ||
|
||
encResp, err := p.api.Encoding.Encodings.Start(enc.Id, model.StartEncodingRequest{VodHlsManifests: vodHLSManifests}) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
👍 for using the VodHlsManifests to start the HLS creation
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
the 👍 belongs to @jamescyeh as this is based off code originally written by him :)
return nil, errBitmovinInvalidConfig | ||
} | ||
|
||
api, err := bitmovin.NewBitmovinApi(func(apiClient *common.ApiClient) { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I'd recommend adding support for passing in an organization id. This enables a customer to use their personal API key to kick off encodes, but the encodes themselves are stored within an Organization's context, which allows colleagues to see the same encodes without logging into your personal user.
e.g.
apiClient.TenantOrgId = cfg.Bitmovin.OrganizationId
This is optional and can be left undefined.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Good to know, I'll add this.
} | ||
|
||
func h264ConfigFrom(preset db.Preset, customData *map[string]map[string]interface{}) (model.H264VideoConfiguration, error) { | ||
cfg := model.H264VideoConfiguration{} |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
We've added support for Preset Configurations that can be set on a codec. These are presets to set low-level codec properties (reference frames, b frames, etc) based on Bitmovin's recommendations. Preset enum: https://github.com/bitmovin/bitmovin-api-sdk-go/blob/master/model/preset_configuration.go and their definitions: https://bitmovin.com/docs/encoding/tutorials/how-to-optimize-your-h264-codec-configuration-for-different-use-cases.
May be useful to expose this in a job configuration.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Those look useful, I'll have to check to see how that best fits into the project structure as it sits today, and see what kinds of options are best for exposing special preset functionality provided only in a single or handful of providers.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
thinking out loud, I kind of see this happening more often as we add support for Per-title Encoding, 10 bits, etc. I wonder if we should have something like a providerConfig
being carried around for the specific parameters of a provider so when triggering a job we could validate if the providerConfig
is supported or not.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Yeah that falls in line with my thinking as well. We already have that Capabilities
interface function, that idea could be extended and given more thought.
return model.AacAudioConfiguration{ | ||
Name: fmt.Sprintf("aac_%s_%.0f", bitrate, defaultAACSampleRate), | ||
Bitrate: &convertedBitrate, | ||
Rate: floatToPtr(defaultAACSampleRate), |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
From Bitmovin's side, are there any plans to override the JSON marshalling of each of the models, bypassing any confusion of zero values, and things getting ignored? With code generation, it may be something that could be relatively easy.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Sharing some notes, I still want to take another look and may have more notes later today or tomorrow 😬
Thanks for working on this! :D
@@ -7,6 +7,7 @@ import ( | |||
"github.com/NYTimes/gizmo/server" | |||
"github.com/NYTimes/video-transcoding-api/config" | |||
_ "github.com/NYTimes/video-transcoding-api/provider/bitmovin" | |||
_ "github.com/NYTimes/video-transcoding-api/provider/bitmovinnewsdk" |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Is this using a different API or just a different SDK?
If it's a different SDK or a new API that's already GA, let's have this replace the old provider 😁
provider/bitmovinnewsdk/bitmovin.go
Outdated
) | ||
|
||
// Just to double check the interface is properly implemented | ||
var _ provider.TranscodingProvider = (*bitmovinProvider)(nil) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Let's move this to a test once we have a test suite, though since the factory returns *bitmovinProvider
+ we're registering the factory with provider.Register, this check isn't strictly necessary.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
sounds good, will remove
|
||
const ( | ||
defaultVorbisSampleRate float64 = 48000 | ||
) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Minor: since there's only one constant here, let's not use a block. Also, the type is not needed:
const defaultVorbisSampleRate = 48000
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
+1 I'll update
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This is looking good. Thank you very much for splitting it into multiple files. I don't know how I feel about having multiple packages though, could we have everything in a single package?
Or, if we chose to go the multi-packages route, could we make the helper packages internal? (I've been thinking about making provider packages internal too, just to guarantee no one can depend directly on them).
What do you think?
import "errors" | ||
|
||
// CustomData holds data to set on encodings and configurations to hold relationship state | ||
type CustomData *map[string]map[string]interface{} |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Oh just noticed this. Does it need to be a pointer?
type CustomData *map[string]map[string]interface{} | |
type CustomData map[string]map[string]interface{} |
Or could we have some kind of structured data on our side that then gets marshaled into a JSON-object that looks arbitrary in the bitmovin API? Something like:
type CustomData struct {
Audio struct {
ID string `json:"id"`
} `json:"audio"`
Container struct {
Name string `json:"name"`
} `json:"container"`
Manifest struct {
ID string `json:"id"`
} `json:"manifest"`
}
(not necessarily with inline structs, I'm just being lazy here 🙈 )
dabe57d
to
0e26b5e
Compare
We're opening this PR as a draft and have yet to write tests. We are looking for feedback from the community on this approach. We've moved the Bitmovin provider from a single file to a new structure we think is more suited to extend, test, and maintain.
Our general approach here was to (1) abstract away the details of managing presets from the global scope and instead localize configurations for specific codecs/formats in their own files, with their logic accessible via interfaces, (2) do the same for generation of output "container"s, and (3) follow a similar model for enriching the
JobStatus
report with output information.We are using the new Bitmovin Go SDK found here: https://github.com/bitmovin/bitmovin-api-sdk-go - any help from the folks at Bitmovin to CR this and ensure we're using this alpha-version SDK as intended would be very welcome.