Ejemplo n.º 1
0
    private async Task <bool> ApplyVersionUpdate(MediaItem mediaItem, MediaVersion version, string filePath)
    {
        MediaVersion mediaItemVersion = mediaItem.GetHeadVersion();

        bool durationChange = mediaItemVersion.Duration != version.Duration;

        version.DateUpdated = _localFileSystem.GetLastWriteTime(filePath);

        return(await _metadataRepository.UpdateLocalStatistics(mediaItem, version) && durationChange);
    }
Ejemplo n.º 2
0
 public async Task <Either <BaseError, bool> > RefreshStatistics(
     string ffmpegPath,
     string ffprobePath,
     MediaItem mediaItem)
 {
     try
     {
         string filePath = mediaItem.GetHeadVersion().MediaFiles.Head().Path;
         return(await RefreshStatistics(ffmpegPath, ffprobePath, mediaItem, filePath));
     }
     catch (Exception ex)
     {
         _logger.LogWarning(ex, "Failed to refresh statistics for media item {Id}", mediaItem.Id);
         _client.Notify(ex);
         return(BaseError.New(ex.Message));
     }
 }
    private async Task <Either <BaseError, PlayoutItemWithPath> > CheckForFallbackFiller(
        TvContext dbContext,
        Channel channel,
        DateTimeOffset now)
    {
        // check for channel fallback
        Option <FillerPreset> maybeFallback = await dbContext.FillerPresets
                                              .SelectOneAsync(w => w.Id, w => w.Id == channel.FallbackFillerId);

        // then check for global fallback
        if (maybeFallback.IsNone)
        {
            maybeFallback = await dbContext.ConfigElements
                            .GetValue <int>(ConfigElementKey.FFmpegGlobalFallbackFillerId)
                            .BindT(fillerId => dbContext.FillerPresets.SelectOneAsync(w => w.Id, w => w.Id == fillerId));
        }

        foreach (FillerPreset fallbackPreset in maybeFallback)
        {
            // turn this into a playout item

            var collectionKey      = CollectionKey.ForFillerPreset(fallbackPreset);
            List <MediaItem> items = await MediaItemsForCollection.Collect(
                _mediaCollectionRepository,
                _televisionRepository,
                _artistRepository,
                collectionKey);

            // TODO: shuffle? does it really matter since we loop anyway
            MediaItem item = items[new Random().Next(items.Count)];

            Option <TimeSpan> maybeDuration = await dbContext.PlayoutItems
                                              .Filter(pi => pi.Playout.ChannelId == channel.Id)
                                              .Filter(pi => pi.Start > now.UtcDateTime)
                                              .OrderBy(pi => pi.Start)
                                              .FirstOrDefaultAsync()
                                              .Map(Optional)
                                              .MapT(pi => pi.StartOffset - now);

            MediaVersion version = item.GetHeadVersion();

            version.MediaFiles = await dbContext.MediaFiles
                                 .AsNoTracking()
                                 .Filter(mf => mf.MediaVersionId == version.Id)
                                 .ToListAsync();

            version.Streams = await dbContext.MediaStreams
                              .AsNoTracking()
                              .Filter(ms => ms.MediaVersionId == version.Id)
                              .ToListAsync();

            DateTimeOffset finish = maybeDuration.Match(
                // next playout item exists
                // loop until it starts
                now.Add,
                // no next playout item exists
                // loop for 5 minutes if less than 30s, otherwise play full item
                () => version.Duration < TimeSpan.FromSeconds(30)
                    ? now.AddMinutes(5)
                    : now.Add(version.Duration));

            var playoutItem = new PlayoutItem
            {
                MediaItem   = item,
                MediaItemId = item.Id,
                Start       = now.UtcDateTime,
                Finish      = finish.UtcDateTime,
                FillerKind  = FillerKind.Fallback,
                InPoint     = TimeSpan.Zero,
                OutPoint    = version.Duration
            };

            return(await ValidatePlayoutItemPath(playoutItem));
        }

        return(new UnableToLocatePlayoutItem());
    }
Ejemplo n.º 4
0
    public async Task <Either <BaseError, Dictionary <string, string> > > GetFormatTags(
        string ffprobePath,
        MediaItem mediaItem)
    {
        try
        {
            string mediaItemPath = mediaItem.GetHeadVersion().MediaFiles.Head().Path;
            Either <BaseError, FFprobe> maybeProbe = await GetProbeOutput(ffprobePath, mediaItemPath);

            return(maybeProbe.Match(
                       ffprobe =>
            {
                var result = new Dictionary <string, string>();

                if (!string.IsNullOrWhiteSpace(ffprobe?.format?.tags?.album))
                {
                    result.Add(MetadataFormatTag.Album, ffprobe.format.tags.album);
                }

                if (!string.IsNullOrWhiteSpace(ffprobe?.format?.tags?.albumArtist))
                {
                    result.Add(MetadataFormatTag.AlbumArtist, ffprobe.format.tags.albumArtist);
                }

                if (!string.IsNullOrWhiteSpace(ffprobe?.format?.tags?.artist))
                {
                    result.Add(MetadataFormatTag.Artist, ffprobe.format.tags.artist);

                    // if no album artist is present, use the track artist
                    if (!result.ContainsKey(MetadataFormatTag.AlbumArtist))
                    {
                        result.Add(MetadataFormatTag.AlbumArtist, ffprobe.format.tags.artist);
                    }
                }

                if (!string.IsNullOrWhiteSpace(ffprobe?.format?.tags?.date))
                {
                    result.Add(MetadataFormatTag.Date, ffprobe.format.tags.date);
                }

                if (!string.IsNullOrWhiteSpace(ffprobe?.format?.tags?.genre))
                {
                    result.Add(MetadataFormatTag.Genre, ffprobe.format.tags.genre);
                }

                if (!string.IsNullOrWhiteSpace(ffprobe?.format?.tags?.title))
                {
                    result.Add(MetadataFormatTag.Title, ffprobe.format.tags.title);
                }

                if (!string.IsNullOrWhiteSpace(ffprobe?.format?.tags?.track))
                {
                    result.Add(MetadataFormatTag.Track, ffprobe.format.tags.track);
                }

                return Right <BaseError, Dictionary <string, string> >(result);
            },
                       Left <BaseError, Dictionary <string, string> >));
        }
        catch (Exception ex)
        {
            _logger.LogWarning(ex, "Failed to get format tags for media item {Id}", mediaItem.Id);
            _client.Notify(ex);
            return(BaseError.New(ex.Message));
        }
    }