In theory there should be no change in actual output for no-transition cuts,
even though we're handling the logic in a very different way.
This doesn't actually allow transitions, but sets up most of what is needed
We support all preset transitions in the xfade filter,
as well as a handful of "custom" ones we define.
We only support an audio cross-fade. We may want to support J and L audio cuts (switch audio
before/after the transition) later.
This allows full cuts to support multiple ranges in the same way fast cuts do,
by using multiple inputs to ffmpeg and concat filters joining them.
This will be easy to add transitions to later as this is "just" replacing a concat filter
with an xfade + afade filter.
This should hopefully result in frames on the edge of timestamps being extracted
from a combination of the neighboring segment and the naive one,
so that we don't get errors extracting a frame.
If two cutters modify a video at the same time, youtube may respond with a 409 to one of them.
We want to treat that as a retryable error, and ideally let another cutter finish it instead.
The SQL args were the wrong way around, so we tried to set error to the id.
Thankfully this failed as the id queried is not a valid uuid.
Fix by making args named like every other usage of query()
Previously, determining the correct cut type and setting up the cut iterator
wasn't an operation we expected to be able to fail.
It happened outside all error handling blocks.
However, due to the multi-range work, this can now fail if we are requesting
an unsupported combination of transitions and cut type.
In order to correctly handle this like other cut errors, ie. set to UNEDITED
and set error column, we move this logic into the upload_wrapper right before we iterate
through the resulting cut.
This is the simplest case as we can just cut each range like we already do,
then concat the results.
We still allow for the full design in the database and cutter, but error out if transitions
is ever anything but hard cuts or if it's a full cut.
We also update the restreamer to allow accepting ranges, however for usability we still allow
the old "just one start and end" args.
Note this changes the thrimshim API to give and take the new "video_ranges" and "video_transitions" columns.
In python 3, file.write() may do a partial write and returns the number of characters written.
In order to not lose data, we need to wrap every instance of file.write() with our new
common.writeall() wrapper that loops until the data is actually written.
Check that open() calls for reading and writing use binary modes
Use alpine version with py3-pip package
Use python3 in Dockerfile CMD
Remove sys.setdefaultencoding() "hack"
Simplify ensure_directory() in common.common package
In order for the upcoming playlist manager to be able to use the DB `tags` column to know
what tags a video has, all the tags it needs need to be present.
Previously, this was a problem because the day and category tags only get added at the cutter
and so wouldn't be listed.
This moves them so they are added when parsing the row in sheetsync.
It also adds the poster moment tag if poster moment is checked.
Note that fully static tags that go on all videos are still only added in cutter,
but the playlist manager doesn't need to care about those (since by definition
they will match every video).
This differs from the existing reset row by only suceeding if the upload is not
in finalizing.
We also make some changes to cutter to handle this situation gracefully.