Beispiel #1
0
    public async Task <Either <BaseError, Unit> > Handle(
        ExtractEmbeddedSubtitles request,
        CancellationToken cancellationToken)
    {
        await using TvContext dbContext = await _dbContextFactory.CreateDbContextAsync(cancellationToken);

        Validation <BaseError, string> validation = await FFmpegPathMustExist(dbContext);

        return(await validation.Match(
                   ffmpegPath => ExtractAll(dbContext, request, ffmpegPath, cancellationToken),
                   error => Task.FromResult <Either <BaseError, Unit> >(error.Join())));
    }
Beispiel #2
0
    private async Task <Either <BaseError, Unit> > ExtractAll(
        TvContext dbContext,
        ExtractEmbeddedSubtitles request,
        string ffmpegPath,
        CancellationToken cancellationToken)
    {
        try
        {
            DateTime now   = DateTime.UtcNow;
            DateTime until = now.AddHours(1);

            var playoutIdsToCheck = new List <int>();

            // only check the requested playout if subtitles are enabled
            Option <Playout> requestedPlayout = await dbContext.Playouts
                                                .Filter(p => p.Channel.SubtitleMode != ChannelSubtitleMode.None)
                                                .SelectOneAsync(p => p.Id, p => p.Id == request.PlayoutId.IfNone(-1));

            playoutIdsToCheck.AddRange(requestedPlayout.Map(p => p.Id));

            // check all playouts (that have subtitles enabled) if none were passed
            if (request.PlayoutId.IsNone)
            {
                playoutIdsToCheck = dbContext.Playouts
                                    .Filter(p => p.Channel.SubtitleMode != ChannelSubtitleMode.None)
                                    .Map(p => p.Id)
                                    .ToList();
            }

            if (playoutIdsToCheck.Count == 0)
            {
                foreach (int playoutId in request.PlayoutId)
                {
                    _logger.LogDebug(
                        "Playout {PlayoutId} does not have subtitles enabled; nothing to extract",
                        playoutId);
                    return(Unit.Default);
                }

                _logger.LogDebug("No playouts have subtitles enabled; nothing to extract");
                return(Unit.Default);
            }

            _logger.LogDebug("Checking playouts {PlayoutIds} for text subtitles to extract", playoutIdsToCheck);

            // find all playout items in the next hour
            List <PlayoutItem> playoutItems = await dbContext.PlayoutItems
                                              .Filter(pi => playoutIdsToCheck.Contains(pi.PlayoutId))
                                              .Filter(pi => pi.Finish >= DateTime.UtcNow)
                                              .Filter(pi => pi.Start <= until)
                                              .ToListAsync(cancellationToken);

            // TODO: support other media kinds (movies, other videos, etc)

            var mediaItemIds = playoutItems.Map(pi => pi.MediaItemId).ToList();

            // filter for subtitles that need extraction
            List <int> unextractedMediaItemIds =
                await GetUnextractedMediaItemIds(dbContext, mediaItemIds, cancellationToken);

            if (unextractedMediaItemIds.Any())
            {
                _logger.LogDebug(
                    "Found media items {MediaItemIds} with text subtitles to extract for playouts {PlayoutIds}",
                    unextractedMediaItemIds,
                    playoutIdsToCheck);
            }
            else
            {
                _logger.LogDebug("Found no text subtitles to extract for playouts {PlayoutIds}", playoutIdsToCheck);
            }

            // sort by start time
            var toUpdate = playoutItems
                           .Filter(pi => pi.Finish >= DateTime.UtcNow)
                           .DistinctBy(pi => pi.MediaItemId)
                           .Filter(pi => unextractedMediaItemIds.Contains(pi.MediaItemId))
                           .OrderBy(pi => pi.StartOffset)
                           .Map(pi => pi.MediaItemId)
                           .ToList();

            foreach (int mediaItemId in toUpdate)
            {
                if (cancellationToken.IsCancellationRequested)
                {
                    return(Unit.Default);
                }

                PlayoutItem pi = playoutItems.Find(pi => pi.MediaItemId == mediaItemId);
                _logger.LogDebug("Extracting subtitles for item with start time {StartTime}", pi?.StartOffset);

                // extract subtitles and fonts for each item and update db
                await ExtractSubtitles(dbContext, mediaItemId, ffmpegPath, cancellationToken);

                // await ExtractFonts(dbContext, episodeId, ffmpegPath, cancellationToken);
            }

            return(Unit.Default);
        }
        catch (TaskCanceledException)
        {
            return(Unit.Default);
        }
    }