< Summary - Jellyfin

Information
Class: Jellyfin.Api.Controllers.VideosController
Assembly: Jellyfin.Api
File(s): /srv/git/jellyfin/Jellyfin.Api/Controllers/VideosController.cs
Line coverage
0%
Covered lines: 0
Uncovered lines: 249
Coverable lines: 249
Total lines: 662
Line coverage: 0%
Branch coverage
0%
Covered branches: 0
Total branches: 70
Branch coverage: 0%
Method coverage

Feature is only available for sponsors

Upgrade to PRO version

Coverage history

Coverage history 0 25 50 75 100 1/23/2026 - 12:11:06 AM Line coverage: 0% (0/91) Branch coverage: 0% (0/10) Total lines: 6584/19/2026 - 12:14:27 AM Line coverage: 0% (0/248) Branch coverage: 0% (0/66) Total lines: 6584/27/2026 - 12:15:04 AM Line coverage: 0% (0/248) Branch coverage: 0% (0/66) Total lines: 6595/4/2026 - 12:15:16 AM Line coverage: 0% (0/249) Branch coverage: 0% (0/70) Total lines: 662 1/23/2026 - 12:11:06 AM Line coverage: 0% (0/91) Branch coverage: 0% (0/10) Total lines: 6584/19/2026 - 12:14:27 AM Line coverage: 0% (0/248) Branch coverage: 0% (0/66) Total lines: 6584/27/2026 - 12:15:04 AM Line coverage: 0% (0/248) Branch coverage: 0% (0/66) Total lines: 6595/4/2026 - 12:15:16 AM Line coverage: 0% (0/249) Branch coverage: 0% (0/70) Total lines: 662

Coverage delta

Coverage delta 1 -1

Metrics

MethodBranch coverage Crap Score Cyclomatic complexity Line coverage
.ctor(...)100%210%
GetAdditionalPart(...)0%110100%
DeleteAlternateSources()0%110100%
MergeVersions()0%342180%
GetVideoStream()0%1056320%
GetVideoStreamByContainer(...)100%210%

File(s)

/srv/git/jellyfin/Jellyfin.Api/Controllers/VideosController.cs

#LineLine coverage
 1using System;
 2using System.Collections.Generic;
 3using System.ComponentModel.DataAnnotations;
 4using System.Globalization;
 5using System.Linq;
 6using System.Net.Http;
 7using System.Threading;
 8using System.Threading.Tasks;
 9using Jellyfin.Api.Attributes;
 10using Jellyfin.Api.Extensions;
 11using Jellyfin.Api.Helpers;
 12using Jellyfin.Api.ModelBinders;
 13using Jellyfin.Extensions;
 14using MediaBrowser.Common.Api;
 15using MediaBrowser.Common.Configuration;
 16using MediaBrowser.Common.Net;
 17using MediaBrowser.Controller.Configuration;
 18using MediaBrowser.Controller.Dto;
 19using MediaBrowser.Controller.Entities;
 20using MediaBrowser.Controller.Library;
 21using MediaBrowser.Controller.MediaEncoding;
 22using MediaBrowser.Controller.Streaming;
 23using MediaBrowser.Model.Dlna;
 24using MediaBrowser.Model.Dto;
 25using MediaBrowser.Model.Entities;
 26using MediaBrowser.Model.MediaInfo;
 27using MediaBrowser.Model.Net;
 28using MediaBrowser.Model.Querying;
 29using Microsoft.AspNetCore.Authorization;
 30using Microsoft.AspNetCore.Http;
 31using Microsoft.AspNetCore.Mvc;
 32
 33namespace Jellyfin.Api.Controllers;
 34
 35/// <summary>
 36/// The videos controller.
 37/// </summary>
 38[Tags("Video")]
 39public class VideosController : BaseJellyfinApiController
 40{
 41    private readonly ILibraryManager _libraryManager;
 42    private readonly IUserManager _userManager;
 43    private readonly IDtoService _dtoService;
 44    private readonly IMediaSourceManager _mediaSourceManager;
 45    private readonly IServerConfigurationManager _serverConfigurationManager;
 46    private readonly IMediaEncoder _mediaEncoder;
 47    private readonly ITranscodeManager _transcodeManager;
 48    private readonly IHttpClientFactory _httpClientFactory;
 49    private readonly EncodingHelper _encodingHelper;
 50
 51    private readonly TranscodingJobType _transcodingJobType = TranscodingJobType.Progressive;
 52
 53    /// <summary>
 54    /// Initializes a new instance of the <see cref="VideosController"/> class.
 55    /// </summary>
 56    /// <param name="libraryManager">Instance of the <see cref="ILibraryManager"/> interface.</param>
 57    /// <param name="userManager">Instance of the <see cref="IUserManager"/> interface.</param>
 58    /// <param name="dtoService">Instance of the <see cref="IDtoService"/> interface.</param>
 59    /// <param name="mediaSourceManager">Instance of the <see cref="IMediaSourceManager"/> interface.</param>
 60    /// <param name="serverConfigurationManager">Instance of the <see cref="IServerConfigurationManager"/> interface.</p
 61    /// <param name="mediaEncoder">Instance of the <see cref="IMediaEncoder"/> interface.</param>
 62    /// <param name="transcodeManager">Instance of the <see cref="ITranscodeManager"/> interface.</param>
 63    /// <param name="httpClientFactory">Instance of the <see cref="IHttpClientFactory"/> interface.</param>
 64    /// <param name="encodingHelper">Instance of <see cref="EncodingHelper"/>.</param>
 065    public VideosController(
 066        ILibraryManager libraryManager,
 067        IUserManager userManager,
 068        IDtoService dtoService,
 069        IMediaSourceManager mediaSourceManager,
 070        IServerConfigurationManager serverConfigurationManager,
 071        IMediaEncoder mediaEncoder,
 072        ITranscodeManager transcodeManager,
 073        IHttpClientFactory httpClientFactory,
 074        EncodingHelper encodingHelper)
 75    {
 076        _libraryManager = libraryManager;
 077        _userManager = userManager;
 078        _dtoService = dtoService;
 079        _mediaSourceManager = mediaSourceManager;
 080        _serverConfigurationManager = serverConfigurationManager;
 081        _mediaEncoder = mediaEncoder;
 082        _transcodeManager = transcodeManager;
 083        _httpClientFactory = httpClientFactory;
 084        _encodingHelper = encodingHelper;
 085    }
 86
 87    /// <summary>
 88    /// Gets additional parts for a video.
 89    /// </summary>
 90    /// <param name="itemId">The item id.</param>
 91    /// <param name="userId">Optional. Filter by user id, and attach user data.</param>
 92    /// <response code="200">Additional parts returned.</response>
 93    /// <returns>A <see cref="QueryResult{BaseItemDto}"/> with the parts.</returns>
 94    [HttpGet("{itemId}/AdditionalParts")]
 95    [Authorize]
 96    [ProducesResponseType(StatusCodes.Status200OK)]
 97    public ActionResult<QueryResult<BaseItemDto>> GetAdditionalPart([FromRoute, Required] Guid itemId, [FromQuery] Guid?
 98    {
 099        userId = RequestHelpers.GetUserId(User, userId);
 0100        var user = userId.IsNullOrEmpty()
 0101            ? null
 0102            : _userManager.GetUserById(userId.Value);
 103
 0104        var item = itemId.IsEmpty()
 0105            ? (userId.IsNullOrEmpty()
 0106                ? _libraryManager.RootFolder
 0107                : _libraryManager.GetUserRootFolder())
 0108            : _libraryManager.GetItemById<BaseItem>(itemId, user);
 0109        if (item is null)
 110        {
 0111            return NotFound();
 112        }
 113
 0114        var dtoOptions = new DtoOptions();
 115
 116        BaseItemDto[] items;
 0117        if (item is Video video)
 118        {
 0119            items = video.GetAdditionalParts()
 0120                .Select(i => _dtoService.GetBaseItemDto(i, dtoOptions, user, video))
 0121                .ToArray();
 122        }
 123        else
 124        {
 0125            items = Array.Empty<BaseItemDto>();
 126        }
 127
 0128        var result = new QueryResult<BaseItemDto>(items);
 0129        return result;
 130    }
 131
 132    /// <summary>
 133    /// Removes alternate video sources.
 134    /// </summary>
 135    /// <param name="itemId">The item id.</param>
 136    /// <response code="204">Alternate sources deleted.</response>
 137    /// <response code="404">Video not found.</response>
 138    /// <returns>A <see cref="NoContentResult"/> indicating success, or a <see cref="NotFoundResult"/> if the video does
 139    [HttpDelete("{itemId}/AlternateSources")]
 140    [Authorize(Policy = Policies.RequiresElevation)]
 141    [ProducesResponseType(StatusCodes.Status204NoContent)]
 142    [ProducesResponseType(StatusCodes.Status404NotFound)]
 143    public async Task<ActionResult> DeleteAlternateSources([FromRoute, Required] Guid itemId)
 144    {
 0145        var item = _libraryManager.GetItemById<Video>(itemId, User.GetUserId());
 0146        if (item is null)
 147        {
 0148            return NotFound();
 149        }
 150
 0151        if (item.LinkedAlternateVersions.Length == 0 && item.PrimaryVersionId.HasValue)
 152        {
 0153            item = _libraryManager.GetItemById<Video>(item.PrimaryVersionId.Value);
 154        }
 155
 0156        if (item is null)
 157        {
 0158            return NotFound();
 159        }
 160
 0161        foreach (var link in _libraryManager.GetLinkedAlternateVersions(item))
 162        {
 0163            link.SetPrimaryVersionId(null);
 0164            link.LinkedAlternateVersions = Array.Empty<LinkedChild>();
 165
 0166            await link.UpdateToRepositoryAsync(ItemUpdateType.MetadataEdit, CancellationToken.None).ConfigureAwait(false
 167        }
 168
 0169        item.LinkedAlternateVersions = Array.Empty<LinkedChild>();
 0170        item.SetPrimaryVersionId(null);
 0171        await item.UpdateToRepositoryAsync(ItemUpdateType.MetadataEdit, CancellationToken.None).ConfigureAwait(false);
 172
 0173        return NoContent();
 0174    }
 175
 176    /// <summary>
 177    /// Merges videos into a single record.
 178    /// </summary>
 179    /// <param name="ids">Item id list. This allows multiple, comma delimited.</param>
 180    /// <response code="204">Videos merged.</response>
 181    /// <response code="400">Supply at least 2 video ids.</response>
 182    /// <returns>A <see cref="NoContentResult"/> indicating success, or a <see cref="BadRequestResult"/> if less than tw
 183    [HttpPost("MergeVersions")]
 184    [Authorize(Policy = Policies.RequiresElevation)]
 185    [ProducesResponseType(StatusCodes.Status204NoContent)]
 186    [ProducesResponseType(StatusCodes.Status400BadRequest)]
 187    public async Task<ActionResult> MergeVersions([FromQuery, Required, ModelBinder(typeof(CommaDelimitedCollectionModel
 188    {
 0189        var userId = User.GetUserId();
 0190        var items = ids
 0191            .Select(i => _libraryManager.GetItemById<BaseItem>(i, userId))
 0192            .OfType<Video>()
 0193            .OrderBy(i => i.Id)
 0194            .ToList();
 195
 0196        if (items.Count < 2)
 197        {
 0198            return BadRequest("Please supply at least two videos to merge.");
 199        }
 200
 0201        var primaryVersion = items.FirstOrDefault(i => i.MediaSourceCount > 1 && !i.PrimaryVersionId.HasValue);
 0202        if (primaryVersion is null)
 203        {
 0204            primaryVersion = items
 0205                .OrderBy(i =>
 0206                {
 0207                    if (i.Video3DFormat.HasValue || i.VideoType != VideoType.VideoFile)
 0208                    {
 0209                        return 1;
 0210                    }
 0211
 0212                    return 0;
 0213                })
 0214                .ThenByDescending(i => i.GetDefaultVideoStream()?.Width ?? 0)
 0215                .First();
 216        }
 217
 0218        var alternateVersionsOfPrimary = primaryVersion.LinkedAlternateVersions.ToList();
 219
 0220        foreach (var item in items.Where(i => !i.Id.Equals(primaryVersion.Id)))
 221        {
 0222            item.SetPrimaryVersionId(primaryVersion.Id);
 223
 0224            await item.UpdateToRepositoryAsync(ItemUpdateType.MetadataEdit, CancellationToken.None).ConfigureAwait(false
 225
 226            // Re-route any playlist/collection references from this item to the primary
 0227            await _libraryManager.RerouteLinkedChildReferencesAsync(item.Id, primaryVersion.Id).ConfigureAwait(false);
 228
 0229            if (!alternateVersionsOfPrimary.Any(i => i.ItemId.HasValue && i.ItemId.Value.Equals(item.Id)))
 230            {
 0231                alternateVersionsOfPrimary.Add(new LinkedChild
 0232                {
 0233                    ItemId = item.Id,
 0234                    Type = LinkedChildType.LinkedAlternateVersion
 0235                });
 236            }
 237
 0238            foreach (var linkedItem in item.LinkedAlternateVersions)
 239            {
 0240                if (linkedItem.ItemId.HasValue && !alternateVersionsOfPrimary.Any(i => i.ItemId.HasValue && i.ItemId.Val
 241                {
 0242                    alternateVersionsOfPrimary.Add(linkedItem);
 243                }
 244            }
 245
 0246            if (item.LinkedAlternateVersions.Length > 0)
 247            {
 0248                item.LinkedAlternateVersions = Array.Empty<LinkedChild>();
 0249                await item.UpdateToRepositoryAsync(ItemUpdateType.MetadataEdit, CancellationToken.None).ConfigureAwait(f
 250            }
 0251        }
 252
 0253        primaryVersion.LinkedAlternateVersions = alternateVersionsOfPrimary.ToArray();
 0254        await primaryVersion.UpdateToRepositoryAsync(ItemUpdateType.MetadataEdit, CancellationToken.None).ConfigureAwait
 0255        return NoContent();
 0256    }
 257
 258    /// <summary>
 259    /// Gets a video stream.
 260    /// </summary>
 261    /// <param name="itemId">The item id.</param>
 262    /// <param name="container">The video container. Possible values are: ts, webm, asf, wmv, ogv, mp4, m4v, mkv, mpeg, 
 263    /// <param name="static">Optional. If true, the original file will be streamed statically without any encoding. Use 
 264    /// <param name="params">The streaming parameters.</param>
 265    /// <param name="tag">The tag.</param>
 266    /// <param name="deviceProfileId">Optional. The dlna device profile id to utilize.</param>
 267    /// <param name="playSessionId">The play session id.</param>
 268    /// <param name="segmentContainer">The segment container.</param>
 269    /// <param name="segmentLength">The segment length.</param>
 270    /// <param name="minSegments">The minimum number of segments.</param>
 271    /// <param name="mediaSourceId">The media version id, if playing an alternate version.</param>
 272    /// <param name="deviceId">The device id of the client requesting. Used to stop encoding processes when needed.</par
 273    /// <param name="audioCodec">Optional. Specify an audio codec to encode to, e.g. mp3. If omitted the server will aut
 274    /// <param name="enableAutoStreamCopy">Whether or not to allow automatic stream copy if requested values match the o
 275    /// <param name="allowVideoStreamCopy">Whether or not to allow copying of the video stream url.</param>
 276    /// <param name="allowAudioStreamCopy">Whether or not to allow copying of the audio stream url.</param>
 277    /// <param name="audioSampleRate">Optional. Specify a specific audio sample rate, e.g. 44100.</param>
 278    /// <param name="maxAudioBitDepth">Optional. The maximum audio bit depth.</param>
 279    /// <param name="audioBitRate">Optional. Specify an audio bitrate to encode to, e.g. 128000. If omitted this will be
 280    /// <param name="audioChannels">Optional. Specify a specific number of audio channels to encode to, e.g. 2.</param>
 281    /// <param name="maxAudioChannels">Optional. Specify a maximum number of audio channels to encode to, e.g. 2.</param
 282    /// <param name="profile">Optional. Specify a specific an encoder profile (varies by encoder), e.g. main, baseline, 
 283    /// <param name="level">Optional. Specify a level for the encoder profile (varies by encoder), e.g. 3, 3.1.</param>
 284    /// <param name="framerate">Optional. A specific video framerate to encode to, e.g. 23.976. Generally this should be
 285    /// <param name="maxFramerate">Optional. A specific maximum video framerate to encode to, e.g. 23.976. Generally thi
 286    /// <param name="copyTimestamps">Whether or not to copy timestamps when transcoding with an offset. Defaults to fals
 287    /// <param name="startTimeTicks">Optional. Specify a starting offset, in ticks. 1 tick = 10000 ms.</param>
 288    /// <param name="width">Optional. The fixed horizontal resolution of the encoded video.</param>
 289    /// <param name="height">Optional. The fixed vertical resolution of the encoded video.</param>
 290    /// <param name="maxWidth">Optional. The maximum horizontal resolution of the encoded video.</param>
 291    /// <param name="maxHeight">Optional. The maximum vertical resolution of the encoded video.</param>
 292    /// <param name="videoBitRate">Optional. Specify a video bitrate to encode to, e.g. 500000. If omitted this will be 
 293    /// <param name="subtitleStreamIndex">Optional. The index of the subtitle stream to use. If omitted no subtitles wil
 294    /// <param name="subtitleMethod">Optional. Specify the subtitle delivery method.</param>
 295    /// <param name="maxRefFrames">Optional.</param>
 296    /// <param name="maxVideoBitDepth">Optional. The maximum video bit depth.</param>
 297    /// <param name="requireAvc">Optional. Whether to require avc.</param>
 298    /// <param name="deInterlace">Optional. Whether to deinterlace the video.</param>
 299    /// <param name="requireNonAnamorphic">Optional. Whether to require a non anamorphic stream.</param>
 300    /// <param name="transcodingMaxAudioChannels">Optional. The maximum number of audio channels to transcode.</param>
 301    /// <param name="cpuCoreLimit">Optional. The limit of how many cpu cores to use.</param>
 302    /// <param name="liveStreamId">The live stream id.</param>
 303    /// <param name="enableMpegtsM2TsMode">Optional. Whether to enable the MpegtsM2Ts mode.</param>
 304    /// <param name="videoCodec">Optional. Specify a video codec to encode to, e.g. h264. If omitted the server will aut
 305    /// <param name="subtitleCodec">Optional. Specify a subtitle codec to encode to.</param>
 306    /// <param name="transcodeReasons">Optional. The transcoding reason.</param>
 307    /// <param name="audioStreamIndex">Optional. The index of the audio stream to use. If omitted the first audio stream
 308    /// <param name="videoStreamIndex">Optional. The index of the video stream to use. If omitted the first video stream
 309    /// <param name="context">Optional. The <see cref="EncodingContext"/>.</param>
 310    /// <param name="streamOptions">Optional. The streaming options.</param>
 311    /// <param name="enableAudioVbrEncoding">Optional. Whether to enable Audio Encoding.</param>
 312    /// <response code="200">Video stream returned.</response>
 313    /// <returns>A <see cref="FileResult"/> containing the audio file.</returns>
 314    [HttpGet("{itemId}/stream")]
 315    [HttpHead("{itemId}/stream", Name = "HeadVideoStream")]
 316    [ProducesResponseType(StatusCodes.Status200OK)]
 317    [ProducesVideoFile]
 318    public async Task<ActionResult> GetVideoStream(
 319        [FromRoute, Required] Guid itemId,
 320        [FromQuery] [RegularExpression(EncodingHelper.ContainerValidationRegexStr)] string? container,
 321        [FromQuery] bool? @static,
 322        [FromQuery] string? @params,
 323        [FromQuery] string? tag,
 324        [FromQuery, ParameterObsolete] string? deviceProfileId,
 325        [FromQuery] string? playSessionId,
 326        [FromQuery] [RegularExpression(EncodingHelper.ContainerValidationRegexStr)] string? segmentContainer,
 327        [FromQuery] int? segmentLength,
 328        [FromQuery] int? minSegments,
 329        [FromQuery] string? mediaSourceId,
 330        [FromQuery] string? deviceId,
 331        [FromQuery] [RegularExpression(EncodingHelper.ContainerValidationRegexStr)] string? audioCodec,
 332        [FromQuery] bool? enableAutoStreamCopy,
 333        [FromQuery] bool? allowVideoStreamCopy,
 334        [FromQuery] bool? allowAudioStreamCopy,
 335        [FromQuery] int? audioSampleRate,
 336        [FromQuery] int? maxAudioBitDepth,
 337        [FromQuery] int? audioBitRate,
 338        [FromQuery] int? audioChannels,
 339        [FromQuery] int? maxAudioChannels,
 340        [FromQuery] string? profile,
 341        [FromQuery] [RegularExpression(EncodingHelper.LevelValidationRegexStr)] string? level,
 342        [FromQuery] float? framerate,
 343        [FromQuery] float? maxFramerate,
 344        [FromQuery] bool? copyTimestamps,
 345        [FromQuery] long? startTimeTicks,
 346        [FromQuery] int? width,
 347        [FromQuery] int? height,
 348        [FromQuery] int? maxWidth,
 349        [FromQuery] int? maxHeight,
 350        [FromQuery] int? videoBitRate,
 351        [FromQuery] int? subtitleStreamIndex,
 352        [FromQuery] SubtitleDeliveryMethod? subtitleMethod,
 353        [FromQuery] int? maxRefFrames,
 354        [FromQuery] int? maxVideoBitDepth,
 355        [FromQuery] bool? requireAvc,
 356        [FromQuery] bool? deInterlace,
 357        [FromQuery] bool? requireNonAnamorphic,
 358        [FromQuery] int? transcodingMaxAudioChannels,
 359        [FromQuery] int? cpuCoreLimit,
 360        [FromQuery] string? liveStreamId,
 361        [FromQuery] bool? enableMpegtsM2TsMode,
 362        [FromQuery] [RegularExpression(EncodingHelper.ContainerValidationRegexStr)] string? videoCodec,
 363        [FromQuery] [RegularExpression(EncodingHelper.ContainerValidationRegexStr)] string? subtitleCodec,
 364        [FromQuery] string? transcodeReasons,
 365        [FromQuery] int? audioStreamIndex,
 366        [FromQuery] int? videoStreamIndex,
 367        [FromQuery] EncodingContext? context,
 368        [FromQuery] Dictionary<string, string> streamOptions,
 369        [FromQuery] bool enableAudioVbrEncoding = true)
 370    {
 0371        var isHeadRequest = Request.Method == System.Net.WebRequestMethods.Http.Head;
 372        // CTS lifecycle is managed internally.
 0373        var cancellationTokenSource = new CancellationTokenSource();
 0374        var streamingRequest = new VideoRequestDto
 0375        {
 0376            Id = itemId,
 0377            Container = container,
 0378            Static = @static ?? false,
 0379            Params = @params,
 0380            Tag = tag,
 0381            PlaySessionId = playSessionId,
 0382            SegmentContainer = segmentContainer,
 0383            SegmentLength = segmentLength,
 0384            MinSegments = minSegments,
 0385            MediaSourceId = mediaSourceId,
 0386            DeviceId = deviceId,
 0387            AudioCodec = audioCodec,
 0388            EnableAutoStreamCopy = enableAutoStreamCopy ?? true,
 0389            AllowAudioStreamCopy = allowAudioStreamCopy ?? true,
 0390            AllowVideoStreamCopy = allowVideoStreamCopy ?? true,
 0391            AudioSampleRate = audioSampleRate,
 0392            MaxAudioChannels = maxAudioChannels,
 0393            AudioBitRate = audioBitRate,
 0394            MaxAudioBitDepth = maxAudioBitDepth,
 0395            AudioChannels = audioChannels,
 0396            Profile = profile,
 0397            Level = level,
 0398            Framerate = framerate,
 0399            MaxFramerate = maxFramerate,
 0400            CopyTimestamps = copyTimestamps ?? false,
 0401            StartTimeTicks = startTimeTicks,
 0402            Width = width,
 0403            Height = height,
 0404            MaxWidth = maxWidth,
 0405            MaxHeight = maxHeight,
 0406            VideoBitRate = videoBitRate,
 0407            SubtitleStreamIndex = subtitleStreamIndex,
 0408            SubtitleMethod = subtitleMethod ?? SubtitleDeliveryMethod.Encode,
 0409            MaxRefFrames = maxRefFrames,
 0410            MaxVideoBitDepth = maxVideoBitDepth,
 0411            RequireAvc = requireAvc ?? false,
 0412            DeInterlace = deInterlace ?? false,
 0413            RequireNonAnamorphic = requireNonAnamorphic ?? false,
 0414            TranscodingMaxAudioChannels = transcodingMaxAudioChannels,
 0415            CpuCoreLimit = cpuCoreLimit,
 0416            LiveStreamId = liveStreamId,
 0417            EnableMpegtsM2TsMode = enableMpegtsM2TsMode ?? false,
 0418            VideoCodec = videoCodec,
 0419            SubtitleCodec = subtitleCodec,
 0420            TranscodeReasons = transcodeReasons,
 0421            AudioStreamIndex = audioStreamIndex,
 0422            VideoStreamIndex = videoStreamIndex,
 0423            Context = context ?? EncodingContext.Streaming,
 0424            StreamOptions = streamOptions,
 0425            EnableAudioVbrEncoding = enableAudioVbrEncoding
 0426        };
 427
 0428        var state = await StreamingHelpers.GetStreamingState(
 0429                streamingRequest,
 0430                HttpContext,
 0431                _mediaSourceManager,
 0432                _userManager,
 0433                _libraryManager,
 0434                _serverConfigurationManager,
 0435                _mediaEncoder,
 0436                _encodingHelper,
 0437                _transcodeManager,
 0438                _transcodingJobType,
 0439                cancellationTokenSource.Token)
 0440            .ConfigureAwait(false);
 441
 0442        if (@static.HasValue && @static.Value && state.DirectStreamProvider is not null)
 443        {
 0444            var liveStreamInfo = _mediaSourceManager.GetLiveStreamInfo(streamingRequest.LiveStreamId);
 0445            if (liveStreamInfo is null)
 446            {
 0447                return NotFound();
 448            }
 449
 0450            var liveStream = new ProgressiveFileStream(liveStreamInfo.GetStream());
 451            // TODO (moved from MediaBrowser.Api): Don't hardcode contentType
 0452            return File(liveStream, MimeTypes.GetMimeType("file.ts"));
 453        }
 454
 455        // Static remote stream
 0456        if (@static.HasValue && @static.Value && state.InputProtocol == MediaProtocol.Http)
 457        {
 0458            var httpClient = _httpClientFactory.CreateClient(NamedClient.Default);
 0459            return await FileStreamResponseHelpers.GetStaticRemoteStreamResult(state, httpClient, HttpContext).Configure
 460        }
 461
 0462        if (@static.HasValue && @static.Value && state.InputProtocol != MediaProtocol.File)
 463        {
 0464            return BadRequest($"Input protocol {state.InputProtocol} cannot be streamed statically");
 465        }
 466
 467        // Static stream
 0468        if (@static.HasValue && @static.Value && !(state.MediaSource.VideoType == VideoType.BluRay || state.MediaSource.
 469        {
 0470            var contentType = state.GetMimeType("." + state.OutputContainer, false) ?? state.GetMimeType(state.MediaPath
 471
 0472            if (state.MediaSource.IsInfiniteStream)
 473            {
 0474                var liveStream = new ProgressiveFileStream(state.MediaPath, null, _transcodeManager);
 0475                return File(liveStream, contentType);
 476            }
 477
 0478            return FileStreamResponseHelpers.GetStaticFileResult(
 0479                state.MediaPath,
 0480                contentType);
 481        }
 482
 483        // Need to start ffmpeg (because media can't be returned directly)
 0484        var encodingOptions = _serverConfigurationManager.GetEncodingOptions();
 0485        var ffmpegCommandLineArguments = _encodingHelper.GetProgressiveVideoFullCommandLine(state, encodingOptions, Enco
 0486        return await FileStreamResponseHelpers.GetTranscodedFile(
 0487            state,
 0488            isHeadRequest,
 0489            HttpContext,
 0490            _transcodeManager,
 0491            ffmpegCommandLineArguments,
 0492            _transcodingJobType,
 0493            cancellationTokenSource).ConfigureAwait(false);
 0494    }
 495
 496    /// <summary>
 497    /// Gets a video stream.
 498    /// </summary>
 499    /// <param name="itemId">The item id.</param>
 500    /// <param name="container">The video container. Possible values are: ts, webm, asf, wmv, ogv, mp4, m4v, mkv, mpeg, 
 501    /// <param name="static">Optional. If true, the original file will be streamed statically without any encoding. Use 
 502    /// <param name="params">The streaming parameters.</param>
 503    /// <param name="tag">The tag.</param>
 504    /// <param name="deviceProfileId">Optional. The dlna device profile id to utilize.</param>
 505    /// <param name="playSessionId">The play session id.</param>
 506    /// <param name="segmentContainer">The segment container.</param>
 507    /// <param name="segmentLength">The segment length.</param>
 508    /// <param name="minSegments">The minimum number of segments.</param>
 509    /// <param name="mediaSourceId">The media version id, if playing an alternate version.</param>
 510    /// <param name="deviceId">The device id of the client requesting. Used to stop encoding processes when needed.</par
 511    /// <param name="audioCodec">Optional. Specify an audio codec to encode to, e.g. mp3. If omitted the server will aut
 512    /// <param name="enableAutoStreamCopy">Whether or not to allow automatic stream copy if requested values match the o
 513    /// <param name="allowVideoStreamCopy">Whether or not to allow copying of the video stream url.</param>
 514    /// <param name="allowAudioStreamCopy">Whether or not to allow copying of the audio stream url.</param>
 515    /// <param name="audioSampleRate">Optional. Specify a specific audio sample rate, e.g. 44100.</param>
 516    /// <param name="maxAudioBitDepth">Optional. The maximum audio bit depth.</param>
 517    /// <param name="audioBitRate">Optional. Specify an audio bitrate to encode to, e.g. 128000. If omitted this will be
 518    /// <param name="audioChannels">Optional. Specify a specific number of audio channels to encode to, e.g. 2.</param>
 519    /// <param name="maxAudioChannels">Optional. Specify a maximum number of audio channels to encode to, e.g. 2.</param
 520    /// <param name="profile">Optional. Specify a specific an encoder profile (varies by encoder), e.g. main, baseline, 
 521    /// <param name="level">Optional. Specify a level for the encoder profile (varies by encoder), e.g. 3, 3.1.</param>
 522    /// <param name="framerate">Optional. A specific video framerate to encode to, e.g. 23.976. Generally this should be
 523    /// <param name="maxFramerate">Optional. A specific maximum video framerate to encode to, e.g. 23.976. Generally thi
 524    /// <param name="copyTimestamps">Whether or not to copy timestamps when transcoding with an offset. Defaults to fals
 525    /// <param name="startTimeTicks">Optional. Specify a starting offset, in ticks. 1 tick = 10000 ms.</param>
 526    /// <param name="width">Optional. The fixed horizontal resolution of the encoded video.</param>
 527    /// <param name="height">Optional. The fixed vertical resolution of the encoded video.</param>
 528    /// <param name="maxWidth">Optional. The maximum horizontal resolution of the encoded video.</param>
 529    /// <param name="maxHeight">Optional. The maximum vertical resolution of the encoded video.</param>
 530    /// <param name="videoBitRate">Optional. Specify a video bitrate to encode to, e.g. 500000. If omitted this will be 
 531    /// <param name="subtitleStreamIndex">Optional. The index of the subtitle stream to use. If omitted no subtitles wil
 532    /// <param name="subtitleMethod">Optional. Specify the subtitle delivery method.</param>
 533    /// <param name="maxRefFrames">Optional.</param>
 534    /// <param name="maxVideoBitDepth">Optional. The maximum video bit depth.</param>
 535    /// <param name="requireAvc">Optional. Whether to require avc.</param>
 536    /// <param name="deInterlace">Optional. Whether to deinterlace the video.</param>
 537    /// <param name="requireNonAnamorphic">Optional. Whether to require a non anamorphic stream.</param>
 538    /// <param name="transcodingMaxAudioChannels">Optional. The maximum number of audio channels to transcode.</param>
 539    /// <param name="cpuCoreLimit">Optional. The limit of how many cpu cores to use.</param>
 540    /// <param name="liveStreamId">The live stream id.</param>
 541    /// <param name="enableMpegtsM2TsMode">Optional. Whether to enable the MpegtsM2Ts mode.</param>
 542    /// <param name="videoCodec">Optional. Specify a video codec to encode to, e.g. h264. If omitted the server will aut
 543    /// <param name="subtitleCodec">Optional. Specify a subtitle codec to encode to.</param>
 544    /// <param name="transcodeReasons">Optional. The transcoding reason.</param>
 545    /// <param name="audioStreamIndex">Optional. The index of the audio stream to use. If omitted the first audio stream
 546    /// <param name="videoStreamIndex">Optional. The index of the video stream to use. If omitted the first video stream
 547    /// <param name="context">Optional. The <see cref="EncodingContext"/>.</param>
 548    /// <param name="streamOptions">Optional. The streaming options.</param>
 549    /// <param name="enableAudioVbrEncoding">Optional. Whether to enable Audio Encoding.</param>
 550    /// <response code="200">Video stream returned.</response>
 551    /// <returns>A <see cref="FileResult"/> containing the audio file.</returns>
 552    [HttpGet("{itemId}/stream.{container}")]
 553    [HttpHead("{itemId}/stream.{container}", Name = "HeadVideoStreamByContainer")]
 554    [ProducesResponseType(StatusCodes.Status200OK)]
 555    [ProducesVideoFile]
 556    public Task<ActionResult> GetVideoStreamByContainer(
 557        [FromRoute, Required] Guid itemId,
 558        [FromRoute, Required] [RegularExpression(EncodingHelper.ContainerValidationRegexStr)] string container,
 559        [FromQuery] bool? @static,
 560        [FromQuery] string? @params,
 561        [FromQuery] string? tag,
 562        [FromQuery] string? deviceProfileId,
 563        [FromQuery] string? playSessionId,
 564        [FromQuery] [RegularExpression(EncodingHelper.ContainerValidationRegexStr)] string? segmentContainer,
 565        [FromQuery] int? segmentLength,
 566        [FromQuery] int? minSegments,
 567        [FromQuery] string? mediaSourceId,
 568        [FromQuery] string? deviceId,
 569        [FromQuery] [RegularExpression(EncodingHelper.ContainerValidationRegexStr)] string? audioCodec,
 570        [FromQuery] bool? enableAutoStreamCopy,
 571        [FromQuery] bool? allowVideoStreamCopy,
 572        [FromQuery] bool? allowAudioStreamCopy,
 573        [FromQuery] int? audioSampleRate,
 574        [FromQuery] int? maxAudioBitDepth,
 575        [FromQuery] int? audioBitRate,
 576        [FromQuery] int? audioChannels,
 577        [FromQuery] int? maxAudioChannels,
 578        [FromQuery] string? profile,
 579        [FromQuery] [RegularExpression(EncodingHelper.LevelValidationRegexStr)] string? level,
 580        [FromQuery] float? framerate,
 581        [FromQuery] float? maxFramerate,
 582        [FromQuery] bool? copyTimestamps,
 583        [FromQuery] long? startTimeTicks,
 584        [FromQuery] int? width,
 585        [FromQuery] int? height,
 586        [FromQuery] int? maxWidth,
 587        [FromQuery] int? maxHeight,
 588        [FromQuery] int? videoBitRate,
 589        [FromQuery] int? subtitleStreamIndex,
 590        [FromQuery] SubtitleDeliveryMethod? subtitleMethod,
 591        [FromQuery] int? maxRefFrames,
 592        [FromQuery] int? maxVideoBitDepth,
 593        [FromQuery] bool? requireAvc,
 594        [FromQuery] bool? deInterlace,
 595        [FromQuery] bool? requireNonAnamorphic,
 596        [FromQuery] int? transcodingMaxAudioChannels,
 597        [FromQuery] int? cpuCoreLimit,
 598        [FromQuery] string? liveStreamId,
 599        [FromQuery] bool? enableMpegtsM2TsMode,
 600        [FromQuery] [RegularExpression(EncodingHelper.ContainerValidationRegexStr)] string? videoCodec,
 601        [FromQuery] [RegularExpression(EncodingHelper.ContainerValidationRegexStr)] string? subtitleCodec,
 602        [FromQuery] string? transcodeReasons,
 603        [FromQuery] int? audioStreamIndex,
 604        [FromQuery] int? videoStreamIndex,
 605        [FromQuery] EncodingContext? context,
 606        [FromQuery] Dictionary<string, string> streamOptions,
 607        [FromQuery] bool enableAudioVbrEncoding = true)
 608    {
 0609        return GetVideoStream(
 0610            itemId,
 0611            container,
 0612            @static,
 0613            @params,
 0614            tag,
 0615            deviceProfileId,
 0616            playSessionId,
 0617            segmentContainer,
 0618            segmentLength,
 0619            minSegments,
 0620            mediaSourceId,
 0621            deviceId,
 0622            audioCodec,
 0623            enableAutoStreamCopy,
 0624            allowVideoStreamCopy,
 0625            allowAudioStreamCopy,
 0626            audioSampleRate,
 0627            maxAudioBitDepth,
 0628            audioBitRate,
 0629            audioChannels,
 0630            maxAudioChannels,
 0631            profile,
 0632            level,
 0633            framerate,
 0634            maxFramerate,
 0635            copyTimestamps,
 0636            startTimeTicks,
 0637            width,
 0638            height,
 0639            maxWidth,
 0640            maxHeight,
 0641            videoBitRate,
 0642            subtitleStreamIndex,
 0643            subtitleMethod,
 0644            maxRefFrames,
 0645            maxVideoBitDepth,
 0646            requireAvc,
 0647            deInterlace,
 0648            requireNonAnamorphic,
 0649            transcodingMaxAudioChannels,
 0650            cpuCoreLimit,
 0651            liveStreamId,
 0652            enableMpegtsM2TsMode,
 0653            videoCodec,
 0654            subtitleCodec,
 0655            transcodeReasons,
 0656            audioStreamIndex,
 0657            videoStreamIndex,
 0658            context,
 0659            streamOptions,
 0660            enableAudioVbrEncoding);
 661    }
 662}

Methods/Properties

.ctor(MediaBrowser.Controller.Library.ILibraryManager,MediaBrowser.Controller.Library.IUserManager,MediaBrowser.Controller.Dto.IDtoService,MediaBrowser.Controller.Library.IMediaSourceManager,MediaBrowser.Controller.Configuration.IServerConfigurationManager,MediaBrowser.Controller.MediaEncoding.IMediaEncoder,MediaBrowser.Controller.MediaEncoding.ITranscodeManager,System.Net.Http.IHttpClientFactory,MediaBrowser.Controller.MediaEncoding.EncodingHelper)
GetAdditionalPart(System.Guid,System.Nullable`1<System.Guid>)
DeleteAlternateSources()
MergeVersions()
GetVideoStream()
GetVideoStreamByContainer(System.Guid,System.String,System.Nullable`1<System.Boolean>,System.String,System.String,System.String,System.String,System.String,System.Nullable`1<System.Int32>,System.Nullable`1<System.Int32>,System.String,System.String,System.String,System.Nullable`1<System.Boolean>,System.Nullable`1<System.Boolean>,System.Nullable`1<System.Boolean>,System.Nullable`1<System.Int32>,System.Nullable`1<System.Int32>,System.Nullable`1<System.Int32>,System.Nullable`1<System.Int32>,System.Nullable`1<System.Int32>,System.String,System.String,System.Nullable`1<System.Single>,System.Nullable`1<System.Single>,System.Nullable`1<System.Boolean>,System.Nullable`1<System.Int64>,System.Nullable`1<System.Int32>,System.Nullable`1<System.Int32>,System.Nullable`1<System.Int32>,System.Nullable`1<System.Int32>,System.Nullable`1<System.Int32>,System.Nullable`1<System.Int32>,System.Nullable`1<MediaBrowser.Model.Dlna.SubtitleDeliveryMethod>,System.Nullable`1<System.Int32>,System.Nullable`1<System.Int32>,System.Nullable`1<System.Boolean>,System.Nullable`1<System.Boolean>,System.Nullable`1<System.Boolean>,System.Nullable`1<System.Int32>,System.Nullable`1<System.Int32>,System.String,System.Nullable`1<System.Boolean>,System.String,System.String,System.String,System.Nullable`1<System.Int32>,System.Nullable`1<System.Int32>,System.Nullable`1<MediaBrowser.Model.Dlna.EncodingContext>,System.Collections.Generic.Dictionary`2<System.String,System.String>,System.Boolean)