The hook_entity_operation hook is provided by Drupal's core entity API, allowing us to declare entity operations dynamically. The function returns an array of operations, with each operation represented as an associative array containing the following key-value pairs:

title: The localized title of the operation.
url: An instance of \Drupal\Core\Url for the operation URL.
weight: The weight of this operation.

as described in the following document

https://api.drupal.org/api/drupal/core!lib!Drupal!Core!Entity!EntityListBuilderInterface.php/function/EntityListBuilderInterface::getOperations/9

Example

<?php

/**
 * Implements hook_entity_operation().
 */
function my_module_entity_operation(EntityInterface $entity) {
  $operations = [];
  // Add action for media video only.
  if ($entity->bundle() == 'video' && $entity->access('update')) {
    $operations['refresh_thumbnail'] = [
      'title' => t('Refresh Thumbnail'),
      'url' => Url::fromRoute('my_module.refresh_thumbnail', [
        'media' => $entity->id(),
      ]),
      'weight' => 150,
    ];
  }
  return $operations;
}

The hook_entity_operation_alter serves as a means to modify existing operations, but it can also be utilized to add new operations, as demonstrated in the example below.

<?php

/**
 * Implements hook_entity_operation_alter().
 */
function my_module_entity_operation_alter(array &$operations, EntityInterface $entity) {
  // Add action for media video only.
  if ($entity->bundle() == 'video' && $entity->access('update')) {
    $operations['refresh_thumbnail'] = [
      'title' => t('Refresh Thumbnail'),
      'url' => Url::fromRoute('my_module.refresh_thumbnail', [
        'media' => $entity->id(),
      ]),
      'weight' => 150,
    ];
  }
}

See it in action https://drupaljournal.com/article/drupal/adding-entity-operation-refresh-video-thumbnail-drupal