Skip to content

Extending

The module defines no hooks, events or permissions and has no *.api.php. Custom code can use its service, its routes and the Media Thumbnails plugin.

Pending frames service

media_thumbnails_client_video.pending_frames (class Drupal\media_thumbnails_client_video\PendingFrames) stores captured frames for the current user until a media item claims them.

Method What it does
save(string $video_filename, string $data): void Stores JPEG data as the current user's frame for a video file name. Throws \InvalidArgumentException when the data is not a JPEG image or is larger than PendingFrames::MAX_BYTES (10 MB).
find(string $source_uri): ?string Returns the URI of the current user's frame for a video file URI, or NULL. A frame for clip.mp4 also matches clip_0.mp4, the name Drupal gives a second file called clip.mp4.
claim(string $source_uri): ?File Moves the frame to client-video-thumbs/ in the video's scheme and returns it as a new permanent file entity, or returns NULL when there is no frame.
deleteExpired(int $max_age): void Deletes frames older than $max_age seconds. Cron calls it with one day.
deleteAll(): void Deletes every pending frame. Uninstalling calls it.
baseDirectory(): string private://media_thumbnails_client_video, or the temporary:// equivalent without a private file system.

File names are matched after transliteration, lowercasing and replacing everything but letters, digits, _ and - with _, because Drupal may rename an uploaded file that way.

For example, to set a frame made elsewhere as the thumbnail of a video that is about to be created:

\Drupal::service('media_thumbnails_client_video.pending_frames')
  ->save('interview.mp4', file_get_contents('/path/to/frame.jpg'));
// Saving a new video media item whose file is interview.mp4 now uses it.

Upload route

media_thumbnails_client_video.upload, POST /media-thumbnails-client/upload, takes multipart/form-data with:

  • thumbnail: the JPEG file.
  • original_filename: the name of the video file the frame belongs to.

It needs an X-CSRF-Token header with the token from /session/token, and a user who can create or edit media (see Permissions). It returns {"status": "success"}, or 400 for missing or non-JPEG data, 403 without access or token, and 413 above 10 MB.

Regenerate route

entity.media.client_thumbnail_regenerate, /media/{media}/client-thumbnail-regenerate, shows the RegenerateThumbnailForm. It is available when the user can update the media item and its source file is a video, and adds a local task to the media item's tabs.

Media Thumbnails integration

  • The plugin is client_video (Drupal\media_thumbnails_client_video\Plugin\MediaThumbnail\ClientVideoThumbnail). Its createThumbnail() claims the current user's frame for the source file.
  • The module replaces the class of Media Thumbnails' plugin.manager.media_thumbnail service with MediaThumbnailManagerOverride. For client_video items, updateThumbnail() only replaces Media's generic icon, and only with a captured frame, and createThumbnail() stores the frame's width and height. Other plugins behave as before. A module that also replaces this service's class must extend MediaThumbnailManagerOverride to keep this behavior.

Front-end libraries

Library Attached to What it does
media_thumbnails_client_video/client_thumbnail File widgets on media entity forms, and the media library's upload form Captures and sends a frame when a video file is chosen.
media_thumbnails_client_video/regenerate_thumbnail The Regenerate Thumbnail form Draws the paused frame into the form before it is submitted.