Skip to content

auto detect video time and update agenda item with said time, and all…#449

Draft
karenunify wants to merge 7 commits into
berkmancenter:stagingfrom
karenunify:44-play-full-video-by-default
Draft

auto detect video time and update agenda item with said time, and all…#449
karenunify wants to merge 7 commits into
berkmancenter:stagingfrom
karenunify:44-play-full-video-by-default

Conversation

@karenunify
Copy link
Copy Markdown
Collaborator

@karenunify karenunify commented May 21, 2026

…ow for youtube and vimeo videos

What is in this PR?

This PR autodetects video length when uploaded to a template, event agenda, or as the waiting room/intro item of a hostless event.

Changes in the codebase

When a video URL is linked, or uploaded via Cloudinary, either to a template, event agenda, or as the waiting room/intro item of a hostless event, the video duration is retrieved from the video service metadata. That time in whole seconds is then automatically added to that template/agenda/waiting room item for hostless events.

In the case of the waiting room on hostless events, the time is now factored in to the breakout room timing, and users will not be sent off to the breakout rooms until after the auto detected video duration, of both the waiting and into videos, if applicable.

If the video duration data isn't readily available, users are prompted to remember to set the slot time to match the video length.

The previously implemented regex for YouTube video detection was somewhat incomplete, and should now be resolved.

Testing this PR

  • Upload a mp4/YouTube/Vimeo video to a template
    • the slot time should automatically update to reflect the time of the video
  • Upload a mp4/YouTube/Vimeo video to an event agenda
    • the agenda item slot time should automatically update to reflect the time of the video
  • Upload a mp4/YouTube/Vimeo videoto an event agenda
    • the slot time should automatically update to reflect the time of the video
  • Upload a mp4/YouTube/Vimeo video to the waiting room/intro item of a hostless event
    • the time slot for the welcome/intro slot should automatically update, as well as the time the intro video plays (if there is a waiting room video), and the breakout time

.

Additional information

AI tools used (if applicable):
Claude Code extension in VS code for best practices and debugging

Copilot AI review requested due to automatic review settings May 21, 2026 16:20
Copy link
Copy Markdown
Contributor

Copilot AI left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

This PR adds automatic video-duration detection (Cloudinary uploads + Vimeo oEmbed + YouTube player metadata) and uses that duration to auto-update agenda slot times and hostless waiting room/buffer timings, improving scheduling accuracy when video media is added.

Changes:

  • Extend MediaHelperService to return upload duration for Cloudinary uploads and fetch Vimeo durations via oEmbed; improve YouTube URL parsing.
  • Wire duration callbacks into agenda item video editing and event waiting room media sections to auto-update time fields and show user feedback.
  • Update time input behavior to reflect external duration changes (controllers update when duration prop changes).

Reviewed changes

Copilot reviewed 10 out of 10 changed files in this pull request and generated 7 comments.

Show a summary per file
File Description
client/test/mocked_classes.mocks.dart Updates mocks for new media helper return types and duration APIs.
client/lib/features/events/features/live_meeting/features/meeting_agenda/presentation/widgets/time_input_form.dart Keeps text controllers in sync when duration changes.
client/lib/features/events/features/live_meeting/features/meeting_agenda/presentation/views/agenda_item_video.dart Adds duration detection hooks (Cloudinary + YouTube) and URL preview routing (YouTube/Vimeo vs generic URL).
client/lib/features/events/features/live_meeting/features/meeting_agenda/presentation/views/agenda_item_video_contract.dart Extends the view contract with a duration-detected notification.
client/lib/features/events/features/live_meeting/features/meeting_agenda/presentation/views/agenda_item_card.dart Auto-updates agenda slot duration when video duration is detected and shows a toast.
client/lib/features/events/features/live_meeting/features/meeting_agenda/presentation/agenda_item_video_presenter.dart Auto-detects YouTube/Vimeo types from pasted URLs and triggers Vimeo duration fetch.
client/lib/features/events/features/event_page/presentation/widgets/media_item_section.dart Returns Cloudinary upload duration and forwards it to callers when the picked media is a video.
client/lib/features/events/features/event_page/presentation/waiting_room_widget_presenter.dart Refactors waiting room time updates to accept Duration instead of minute/second strings.
client/lib/features/events/features/event_page/presentation/views/waiting_room_widget.dart Uses TimeInputForm for durations and auto-updates buffer/intro timings when video duration is detected.
client/lib/core/data/services/media_helper_service.dart Adds duration-carrying return types, improved YouTube ID regex, and Vimeo duration lookup via HTTP.

💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

Comment on lines +70 to +77
if (_mediaHelperService.getYoutubeVideoId(trimmedUrl) != null) {
_model.agendaItemVideoData.type = AgendaItemVideoType.youtube;
} else {
final vimeoId = _mediaHelperService.getVimeoVideoId(trimmedUrl);
if (vimeoId != null) {
_model.agendaItemVideoData.type = AgendaItemVideoType.vimeo;
_fetchAndNotifyVimeoDuration(vimeoId);
}
Copy link
Copy Markdown
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

fixed

Comment on lines +101 to +110
onVideoDurationDetected: (durationInSeconds) {
_presenter.updateWaitingBufferDuration(
Duration(seconds: durationInSeconds),
);
showRegularToast(
context,
'Buffer time updated to ${ prettyDuration(Duration(seconds: durationInSeconds)).replaceAll('minute', 'min').replaceAll('second', 'sec')} to match video length.',
toastType: ToastType.neutral,
);
},
Copy link
Copy Markdown
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

fixed

Comment on lines +165 to +172
onVideoDurationDetected: (durationInSeconds) {
_presenter.updateDuration(Duration(seconds: durationInSeconds));
showRegularToast(
context,
'Intro Length updated to ${prettyDuration(Duration(seconds: durationInSeconds)).replaceAll('minute', 'min').replaceAll('second', 'sec')} to match video length.',
toastType: ToastType.neutral,
);
},
Copy link
Copy Markdown
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

fixed

Comment on lines +308 to +316
onVideoDurationDetected: (durationInSeconds) {
final duration = Duration(seconds: durationInSeconds);
_presenter.updateTime(duration);
showRegularToast(
context,
'Slot time updated to ${_presenter.getFormattedDuration(duration)} to match video length.',
toastType: ToastType.neutral,
);
},
Copy link
Copy Markdown
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

fixed

Co-authored-by: Copilot Autofix powered by AI <175728472+Copilot@users.noreply.github.com>
Copy link
Copy Markdown
Contributor

Copilot AI left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

Copilot reviewed 10 out of 10 changed files in this pull request and generated 5 comments.

Comment on lines +182 to 185
TimeInputForm(
duration: introLengthDuration,
onUpdate: (d) => _presenter.updateDuration(d),
),
Comment on lines +106 to +116
final info = await _pickMediaInfo(
uploadPreset: uploadPreset,
clientAllowedFormats: clientAllowedFormats,
cropping: cropping,
croppingAspectRatio: croppingAspectRatio,
);
if (info == null) return null;
return PickedVideoResult(
url: info.url,
durationInSeconds: info.duration?.round(),
);
Comment thread client/lib/core/data/services/media_helper_service.dart Outdated
Comment on lines 64 to +91
void updateVideoUrl(String url) {
_model.agendaItemVideoData.url = url.trim();
_view.updateView();
final trimmedUrl = url.trim();
_model.agendaItemVideoData.url = trimmedUrl;

// Auto-detect YouTube/Vimeo links so the saved type is correct even when
// the user pastes a link into the generic URL tab.
if (_mediaHelperService.getYoutubeVideoId(trimmedUrl) != null) {
_model.agendaItemVideoData.type = AgendaItemVideoType.youtube;
} else {
final vimeoId = _mediaHelperService.getVimeoVideoId(trimmedUrl);
if (vimeoId != null) {
_model.agendaItemVideoData.type = AgendaItemVideoType.vimeo;
_fetchAndNotifyVimeoDuration(vimeoId);
} else {
_model.agendaItemVideoData.type = AgendaItemVideoType.url;
}
}

_view.updateView();
_helper.updateParent(_model);
}

void _fetchAndNotifyVimeoDuration(String vimeoId) async {
final duration = await _mediaHelperService.fetchVimeoDuration(vimeoId);
if (duration != null) {
_view.notifyVideoDurationDetected(duration);
}
}
Co-authored-by: Copilot Autofix powered by AI <175728472+Copilot@users.noreply.github.com>
@karenunify karenunify marked this pull request as draft May 22, 2026 18:00
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants