From c5c7573d250bc51d5b6228c54c22ce3b08c08c68 Mon Sep 17 00:00:00 2001 From: Jozef Mlich Date: Fri, 4 Dec 2020 10:52:02 +0100 Subject: [PATCH 1/3] #3: add credits --- make-xges.py | 51 ++++++++++++++++++++++++++++++++++++++++++++++++++- 1 file changed, 50 insertions(+), 1 deletion(-) diff --git a/make-xges.py b/make-xges.py index 4bfa4de..0fe31cc 100755 --- a/make-xges.py +++ b/make-xges.py @@ -36,10 +36,12 @@ def __init__(self, opts): # Construct the presentation self.set_track_caps() self.set_project_metadata() + self.add_credits_start() self.add_webcams() self.add_slides() self.add_deskshare() self.add_backdrop() + self.add_credits_end() def _add_layer(self, name): layer = self.timeline.append_layer() @@ -86,7 +88,7 @@ def _add_clip(self, layer, asset, start, inpoint, duration, inpoint += -start start = 0 - clip = layer.add_asset(asset, start, inpoint, duration, + clip = layer.add_asset(asset, self.credits_len + start, inpoint, duration, GES.TrackType.UNKNOWN) for element in clip.find_track_elements( self.video_track, GES.TrackType.VIDEO, GObject.TYPE_NONE): @@ -212,6 +214,51 @@ def add_backdrop(self): self._add_clip(layer, asset, 0, 0, duration, 0, 0, self.opts.width, self.opts.height) + + def add_credits_start(self): + self.credits_len = 0 + if not self.opts.prepend_file: + return + + self.credits_len = len(self.opts.prepend_file) * 3 * Gst.SECOND + + layer = self._add_layer('credits') + for idx, f in enumerate(self.opts.prepend_file): + asset = self._get_asset(f.name) + + start = idx * 3 * Gst.SECOND + + clip = layer.add_asset(asset, start, 0, 3 * Gst.SECOND, GES.TrackType.UNKNOWN) + for element in clip.find_track_elements( + self.video_track, GES.TrackType.VIDEO, GObject.TYPE_NONE): + element.set_child_property("posx", 0) + element.set_child_property("posy", 0) + element.set_child_property("width", self.opts.width) + element.set_child_property("height", self.opts.height) + + + def add_credits_end(self): + if not self.opts.append_file: + return + + duration = self.end_time - self.start_time + + + layer = self._add_layer('credits') + for idx, f in enumerate(self.opts.append_file): + asset = self._get_asset(f.name) + + start = self.credits_len + duration + idx * 3 * Gst.SECOND + + clip = layer.add_asset(asset, start, 0, 3 * Gst.SECOND, GES.TrackType.UNKNOWN) + for element in clip.find_track_elements( + self.video_track, GES.TrackType.VIDEO, GObject.TYPE_NONE): + element.set_child_property("posx", 0) + element.set_child_property("posy", 0) + element.set_child_property("width", self.opts.width) + element.set_child_property("height", self.opts.height) + + def save(self): self.timeline.commit_sync() self.timeline.save_to_uri(file_to_uri(self.opts.project), None, True) @@ -234,6 +281,8 @@ def main(argv): help='Stretch webcam to 16:9 aspect ratio') parser.add_argument('--backdrop', metavar='FILE', type=str, default=None, help='Backdrop image for the project') + parser.add_argument('--prepend-file', type=argparse.FileType('r'), nargs='+') + parser.add_argument('--append-file', type=argparse.FileType('r'), nargs='+') parser.add_argument('basedir', metavar='PRESENTATION-DIR', type=str, help='directory containing BBB presentation assets') parser.add_argument('project', metavar='OUTPUT', type=str, From 4d3f6cc1101c44be4de26778bc8f7920c9a8eeec Mon Sep 17 00:00:00 2001 From: James Henstridge Date: Sun, 27 Dec 2020 17:23:39 +0800 Subject: [PATCH 2/3] make-xges: use _add_clip helper to add opening/closing credits A duration can be set for each card. If no duration is set, 3 seconds is used for images (as before), or the actual duration for video cards. Also rename the options to --opening-credits and --closing-credits. To add multiple cards, the options must be passed multiple times. The nargs='+' mode was conflicting with the positional arguments. --- make-xges.py | 116 ++++++++++++++++++++++++++++----------------------- 1 file changed, 64 insertions(+), 52 deletions(-) diff --git a/make-xges.py b/make-xges.py index 0fe31cc..364a034 100755 --- a/make-xges.py +++ b/make-xges.py @@ -36,12 +36,11 @@ def __init__(self, opts): # Construct the presentation self.set_track_caps() self.set_project_metadata() - self.add_credits_start() + self.add_credits() self.add_webcams() self.add_slides() self.add_deskshare() self.add_backdrop() - self.add_credits_end() def _add_layer(self, name): layer = self.timeline.append_layer() @@ -70,12 +69,13 @@ def _constrain(self, dimensions, bounds): return round(width * max_height / height), max_height def _add_clip(self, layer, asset, start, inpoint, duration, - posx, posy, width, height): - # Skip clips entirely after the end point - if start > self.end_time: - return - # Truncate clips that go past the end point - duration = min(duration, self.end_time - start) + posx, posy, width, height, trim_end=True): + if trim_end: + # Skip clips entirely after the end point + if start > self.end_time: + return + # Truncate clips that go past the end point + duration = min(duration, self.end_time - start) # Skip clips entirely before the start point if start + duration < self.start_time: @@ -88,7 +88,10 @@ def _add_clip(self, layer, asset, start, inpoint, duration, inpoint += -start start = 0 - clip = layer.add_asset(asset, self.credits_len + start, inpoint, duration, + # Offset start point by the length of the opening credits + start += self.opening_length + + clip = layer.add_asset(asset, start, inpoint, duration, GES.TrackType.UNKNOWN) for element in clip.find_track_elements( self.video_track, GES.TrackType.VIDEO, GObject.TYPE_NONE): @@ -123,6 +126,9 @@ def set_track_caps(self): else: self.end_time = round(self.opts.end * Gst.SECOND) + # Offset for the opening credits + self.opening_length = 0 + # Add an encoding profile for the benefit of Pitivi profile = GstPbutils.EncodingContainerProfile.new( 'MP4', 'bbb-render encoding profile', @@ -204,60 +210,62 @@ def add_deskshare(self): def add_backdrop(self): if not self.opts.backdrop: return - # Get duration of webcam footage - webcams_asset = self._get_asset( - os.path.join(self.opts.basedir, 'video/webcams.webm')) - duration = webcams_asset.props.duration - layer = self._add_layer('Backdrop') asset = self._get_asset(self.opts.backdrop) - self._add_clip(layer, asset, 0, 0, duration, + self._add_clip(layer, asset, 0, 0, self.end_time, 0, 0, self.opts.width, self.opts.height) - - def add_credits_start(self): - self.credits_len = 0 - if not self.opts.prepend_file: + def add_credits(self): + if not (self.opts.opening_credits or self.opts.closing_credits): return - self.credits_len = len(self.opts.prepend_file) * 3 * Gst.SECOND - layer = self._add_layer('credits') - for idx, f in enumerate(self.opts.prepend_file): - asset = self._get_asset(f.name) - - start = idx * 3 * Gst.SECOND - - clip = layer.add_asset(asset, start, 0, 3 * Gst.SECOND, GES.TrackType.UNKNOWN) - for element in clip.find_track_elements( - self.video_track, GES.TrackType.VIDEO, GObject.TYPE_NONE): - element.set_child_property("posx", 0) - element.set_child_property("posy", 0) - element.set_child_property("width", self.opts.width) - element.set_child_property("height", self.opts.height) - - - def add_credits_end(self): - if not self.opts.append_file: - return + for fname in self.opts.opening_credits: + duration = None + if ':' in fname: + fname, duration = fname.rsplit(':', 1) + duration = round(float(duration) * Gst.SECOND) + + asset = self._get_asset(fname) + if duration is None: + if asset.is_image(): + duration = 3 * Gst.SECOND + else: + duration = asset.props.duration + + dims = self._get_dimensions(asset) + + dims = self._get_dimensions(asset) + width, height = self._constrain( + dims, (self.opts.width, self.opts.height)) - duration = self.end_time - self.start_time + self._add_clip(layer, asset, 0, 0, duration, + 0, 0, width, height, trim_end=False) + self.opening_length += duration + closing_length = 0 + for fname in self.opts.closing_credits: + duration = None + if ':' in fname: + fname, duration = fname.rsplit(':', 1) + duration = round(float(duration) * Gst.SECOND) - layer = self._add_layer('credits') - for idx, f in enumerate(self.opts.append_file): - asset = self._get_asset(f.name) + asset = self._get_asset(fname) + if duration is None: + if asset.is_image(): + duration = 3 * Gst.SECOND + else: + duration = asset.props.duration - start = self.credits_len + duration + idx * 3 * Gst.SECOND + dims = self._get_dimensions(asset) - clip = layer.add_asset(asset, start, 0, 3 * Gst.SECOND, GES.TrackType.UNKNOWN) - for element in clip.find_track_elements( - self.video_track, GES.TrackType.VIDEO, GObject.TYPE_NONE): - element.set_child_property("posx", 0) - element.set_child_property("posy", 0) - element.set_child_property("width", self.opts.width) - element.set_child_property("height", self.opts.height) + dims = self._get_dimensions(asset) + width, height = self._constrain( + dims, (self.opts.width, self.opts.height)) + self._add_clip(layer, asset, self.end_time + closing_length, 0, + duration, 0, 0, width, height, trim_end=False) + closing_length += duration def save(self): self.timeline.commit_sync() @@ -281,8 +289,12 @@ def main(argv): help='Stretch webcam to 16:9 aspect ratio') parser.add_argument('--backdrop', metavar='FILE', type=str, default=None, help='Backdrop image for the project') - parser.add_argument('--prepend-file', type=argparse.FileType('r'), nargs='+') - parser.add_argument('--append-file', type=argparse.FileType('r'), nargs='+') + parser.add_argument('--opening-credits', metavar='FILE[:DURATION]', + type=str, action='append', default=[], + help='File to use as opening credits (may be repeated)') + parser.add_argument('--closing-credits', metavar='FILE[:DURATION]', + type=str, action='append', default=[], + help='File to use as closing credits (may be repeated)') parser.add_argument('basedir', metavar='PRESENTATION-DIR', type=str, help='directory containing BBB presentation assets') parser.add_argument('project', metavar='OUTPUT', type=str, From b31a006d3f3ec79d11feaf7cff4e814d0d686d20 Mon Sep 17 00:00:00 2001 From: James Henstridge Date: Sun, 27 Dec 2020 18:14:42 +0800 Subject: [PATCH 3/3] README: update documentation --- README.md | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/README.md b/README.md index 22c394f..4784d2a 100644 --- a/README.md +++ b/README.md @@ -51,10 +51,12 @@ Editing Services project. It takes the following optional parameters to influence the project: +* `--start=SECONDS` and `--end=SECONDS` can be used to trim footage from the start or end of the recording. This can be helpful if the recording was started early, or you want to split the recoridng into multiple projects. * `--width=WIDTH` and `--height=HEIGHT` control the dimensions of the video. The default resolution is 1920x1080. * `--webcam-size=PERCENT` controls how much of the frame width will be devoted to the webcam footage. This defaults to 20%. +* `--stretch-webcam` stretches the webcam footage by 33%. This was added to correct the camera aspect ratio in some of our recordings. * `--backdrop=FILE` sets a still image to place behind other elements. This can be used to fill in the empty space in the frame. -* `--skip=SECONDS` allows you to skip ahead from the beginning of the recording. This is useful if recording was started before the actual presentation. +* `--opening-credits=FILE[:DURATION]` and `--closing-credits=FILE[:DURATION]` will add credits to project. These can either be videos or still images (which will default to 3 seconds duration). These options can be repeated to add multiple credits. Currently the project includes the following aspects of the BBB recording: