Since Version 9.3 TYPO3 ships with a nice API to handle meta tags. I was looking for a way to provide a fallback og:image to avoid some randomish results and finally made a custom meta tag manager.

This custom meta tag manager simply slides up the rootline starting from the current page until it finds a page with at least one og:image assigned. It then adds the proper og:image meta tags after resizing the image(s) (to some hardcoded dimensions):

<?php

namespace My\Extension\MetaTag;

use TYPO3\CMS\Core\Resource\FileRepository;
use TYPO3\CMS\Core\Utility\GeneralUtility;
use TYPO3\CMS\Core\Utility\RootlineUtility;
use TYPO3\CMS\Extbase\Service\ImageService;

class OpenGraphMetaTagManager extends \TYPO3\CMS\Seo\MetaTag\OpenGraphMetaTagManager
{
    public function renderAllProperties(): string
    {
        if (array_key_exists('og:image', $this->properties)) {
            return parent::renderAllProperties();
        }

        /** @var FileRepository $fileRepository */
        $fileRepository = GeneralUtility::makeInstance(FileRepository::class);

        $pageUid = $this->getPageWithImage();

        if (null === $pageUid) {
            return parent::renderAllProperties();
        }

        $images = $fileRepository->findByRelation('pages', 'og_image', $pageUid);

        /** @var ImageService $imageService */
        $imageService = GeneralUtility::makeInstance(ImageService::class);

         // multiple og:image tags are allowed so they say
        foreach ($images as $image) {
            $processedImage = $imageService->applyProcessingInstructions(
                $image,
                [
                    'width' => '1200', // Hardcoded width, I know, too lazy
                ]
            );
            $this->addProperty(
                'og:image',
                $imageService->getImageUri($processedImage, true),
                [
                    'url' => $imageService->getImageUri($processedImage, true),
                    'width' => $processedImage->getProperty('width'),
                    'height' => $processedImage->getProperty('height'),
                    'type' => $processedImage->getMimeType(),
                ]
            );
        }

        return parent::renderAllProperties();
    }

    /**
     * @return null|int
     */
    protected function getPageWithImage()
    {
        $rootLineUtility = new RootlineUtility($GLOBALS['TSFE']->id);
        $rootLine = $rootLineUtility->get();

        foreach ($rootLine as $page) {
            if ($page['og_image'] > 0) {
                return $page['uid'];
            }
        }

        return null;
    }
}

To make it work the field og_image has to be added to the rootline by placing the following lines into ext_tables.php:

    if ($GLOBALS['TYPO3_CONF_VARS']['FE']['addRootLineFields'] !== '') {
        $GLOBALS['TYPO3_CONF_VARS']['FE']['addRootLineFields'] .= ',';
    }
    $GLOBALS['TYPO3_CONF_VARS']['FE']['addRootLineFields'] .= 'og_image';

Finally, the meta tag manager has to be registered in ext_localconf.php like so:

$metaTagManagerRegistry = \TYPO3\CMS\Core\Utility\GeneralUtility::makeInstance(\TYPO3\CMS\Core\MetaTag\MetaTagManagerRegistry::class);
$metaTagManagerRegistry->registerManager(
    'my_opengraph',
    \My\Extension\MetaTag\OpenGraphMetaTagManager::class
);

Works as designed ;)