< 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: 92
Coverable lines: 92
Total lines: 664
Line coverage: 0%
Branch coverage
0%
Covered branches: 0
Total branches: 10
Branch coverage: 0%
Method coverage

Feature is only available for sponsors

Upgrade to PRO version

Coverage history

Coverage history 0 25 50 75 100 9/17/2025 - 12:11:23 AM Line coverage: 0% (0/93) Branch coverage: 0% (0/10) Total lines: 66512/1/2025 - 12:11:46 AM Line coverage: 0% (0/92) Branch coverage: 0% (0/10) Total lines: 664 9/17/2025 - 12:11:23 AM Line coverage: 0% (0/93) Branch coverage: 0% (0/10) Total lines: 66512/1/2025 - 12:11:46 AM Line coverage: 0% (0/92) Branch coverage: 0% (0/10) Total lines: 664

Metrics

MethodBranch coverage Crap Score Cyclomatic complexity Line coverage
.ctor(...)100%210%
GetAdditionalPart(...)0%110100%
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>
 38public class VideosController : BaseJellyfinApiController
 39{
 40    private readonly ILibraryManager _libraryManager;
 41    private readonly IUserManager _userManager;
 42    private readonly IDtoService _dtoService;
 43    private readonly IMediaSourceManager _mediaSourceManager;
 44    private readonly IServerConfigurationManager _serverConfigurationManager;
 45    private readonly IMediaEncoder _mediaEncoder;
 46    private readonly ITranscodeManager _transcodeManager;
 47    private readonly IHttpClientFactory _httpClientFactory;
 48    private readonly EncodingHelper _encodingHelper;
 49
 50    private readonly TranscodingJobType _transcodingJobType = TranscodingJobType.Progressive;
 51
 52    /// <summary>
 53    /// Initializes a new instance of the <see cref="VideosController"/> class.
 54    /// </summary>
 55    /// <param name="libraryManager">Instance of the <see cref="ILibraryManager"/> interface.</param>
 56    /// <param name="userManager">Instance of the <see cref="IUserManager"/> interface.</param>
 57    /// <param name="dtoService">Instance of the <see cref="IDtoService"/> interface.</param>
 58    /// <param name="mediaSourceManager">Instance of the <see cref="IMediaSourceManager"/> interface.</param>
 59    /// <param name="serverConfigurationManager">Instance of the <see cref="IServerConfigurationManager"/> interface.</p
 60    /// <param name="mediaEncoder">Instance of the <see cref="IMediaEncoder"/> interface.</param>
 61    /// <param name="transcodeManager">Instance of the <see cref="ITranscodeManager"/> interface.</param>
 62    /// <param name="httpClientFactory">Instance of the <see cref="IHttpClientFactory"/> interface.</param>
 63    /// <param name="encodingHelper">Instance of <see cref="EncodingHelper"/>.</param>
 064    public VideosController(
 065        ILibraryManager libraryManager,
 066        IUserManager userManager,
 067        IDtoService dtoService,
 068        IMediaSourceManager mediaSourceManager,
 069        IServerConfigurationManager serverConfigurationManager,
 070        IMediaEncoder mediaEncoder,
 071        ITranscodeManager transcodeManager,
 072        IHttpClientFactory httpClientFactory,
 073        EncodingHelper encodingHelper)
 74    {
 075        _libraryManager = libraryManager;
 076        _userManager = userManager;
 077        _dtoService = dtoService;
 078        _mediaSourceManager = mediaSourceManager;
 079        _serverConfigurationManager = serverConfigurationManager;
 080        _mediaEncoder = mediaEncoder;
 081        _transcodeManager = transcodeManager;
 082        _httpClientFactory = httpClientFactory;
 083        _encodingHelper = encodingHelper;
 084    }
 85
 86    /// <summary>
 87    /// Gets additional parts for a video.
 88    /// </summary>
 89    /// <param name="itemId">The item id.</param>
 90    /// <param name="userId">Optional. Filter by user id, and attach user data.</param>
 91    /// <response code="200">Additional parts returned.</response>
 92    /// <returns>A <see cref="QueryResult{BaseItemDto}"/> with the parts.</returns>
 93    [HttpGet("{itemId}/AdditionalParts")]
 94    [Authorize]
 95    [ProducesResponseType(StatusCodes.Status200OK)]
 96    public ActionResult<QueryResult<BaseItemDto>> GetAdditionalPart([FromRoute, Required] Guid itemId, [FromQuery] Guid?
 97    {
 098        userId = RequestHelpers.GetUserId(User, userId);
 099        var user = userId.IsNullOrEmpty()
 0100            ? null
 0101            : _userManager.GetUserById(userId.Value);
 102
 0103        var item = itemId.IsEmpty()
 0104            ? (userId.IsNullOrEmpty()
 0105                ? _libraryManager.RootFolder
 0106                : _libraryManager.GetUserRootFolder())
 0107            : _libraryManager.GetItemById<BaseItem>(itemId, user);
 0108        if (item is null)
 109        {
 0110            return NotFound();
 111        }
 112
 0113        var dtoOptions = new DtoOptions();
 114
 115        BaseItemDto[] items;
 0116        if (item is Video video)
 117        {
 0118            items = video.GetAdditionalParts()
 0119                .Select(i => _dtoService.GetBaseItemDto(i, dtoOptions, user, video))
 0120                .ToArray();
 121        }
 122        else
 123        {
 0124            items = Array.Empty<BaseItemDto>();
 125        }
 126
 0127        var result = new QueryResult<BaseItemDto>(items);
 0128        return result;
 129    }
 130
 131    /// <summary>
 132    /// Removes alternate video sources.
 133    /// </summary>
 134    /// <param name="itemId">The item id.</param>
 135    /// <response code="204">Alternate sources deleted.</response>
 136    /// <response code="404">Video not found.</response>
 137    /// <returns>A <see cref="NoContentResult"/> indicating success, or a <see cref="NotFoundResult"/> if the video does
 138    [HttpDelete("{itemId}/AlternateSources")]
 139    [Authorize(Policy = Policies.RequiresElevation)]
 140    [ProducesResponseType(StatusCodes.Status204NoContent)]
 141    [ProducesResponseType(StatusCodes.Status404NotFound)]
 142    public async Task<ActionResult> DeleteAlternateSources([FromRoute, Required] Guid itemId)
 143    {
 144        var item = _libraryManager.GetItemById<Video>(itemId, User.GetUserId());
 145        if (item is null)
 146        {
 147            return NotFound();
 148        }
 149
 150        if (item.LinkedAlternateVersions.Length == 0)
 151        {
 152            item = _libraryManager.GetItemById<Video>(Guid.Parse(item.PrimaryVersionId));
 153        }
 154
 155        if (item is null)
 156        {
 157            return NotFound();
 158        }
 159
 160        foreach (var link in item.GetLinkedAlternateVersions())
 161        {
 162            link.SetPrimaryVersionId(null);
 163            link.LinkedAlternateVersions = Array.Empty<LinkedChild>();
 164
 165            await link.UpdateToRepositoryAsync(ItemUpdateType.MetadataEdit, CancellationToken.None).ConfigureAwait(false
 166        }
 167
 168        item.LinkedAlternateVersions = Array.Empty<LinkedChild>();
 169        item.SetPrimaryVersionId(null);
 170        await item.UpdateToRepositoryAsync(ItemUpdateType.MetadataEdit, CancellationToken.None).ConfigureAwait(false);
 171
 172        return NoContent();
 173    }
 174
 175    /// <summary>
 176    /// Merges videos into a single record.
 177    /// </summary>
 178    /// <param name="ids">Item id list. This allows multiple, comma delimited.</param>
 179    /// <response code="204">Videos merged.</response>
 180    /// <response code="400">Supply at least 2 video ids.</response>
 181    /// <returns>A <see cref="NoContentResult"/> indicating success, or a <see cref="BadRequestResult"/> if less than tw
 182    [HttpPost("MergeVersions")]
 183    [Authorize(Policy = Policies.RequiresElevation)]
 184    [ProducesResponseType(StatusCodes.Status204NoContent)]
 185    [ProducesResponseType(StatusCodes.Status400BadRequest)]
 186    public async Task<ActionResult> MergeVersions([FromQuery, Required, ModelBinder(typeof(CommaDelimitedCollectionModel
 187    {
 188        var userId = User.GetUserId();
 189        var items = ids
 190            .Select(i => _libraryManager.GetItemById<BaseItem>(i, userId))
 191            .OfType<Video>()
 192            .OrderBy(i => i.Id)
 193            .ToList();
 194
 195        if (items.Count < 2)
 196        {
 197            return BadRequest("Please supply at least two videos to merge.");
 198        }
 199
 200        var primaryVersion = items.FirstOrDefault(i => i.MediaSourceCount > 1 && string.IsNullOrEmpty(i.PrimaryVersionId
 201        if (primaryVersion is null)
 202        {
 203            primaryVersion = items
 204                .OrderBy(i =>
 205                {
 206                    if (i.Video3DFormat.HasValue || i.VideoType != VideoType.VideoFile)
 207                    {
 208                        return 1;
 209                    }
 210
 211                    return 0;
 212                })
 213                .ThenByDescending(i => i.GetDefaultVideoStream()?.Width ?? 0)
 214                .First();
 215        }
 216
 217        var alternateVersionsOfPrimary = primaryVersion.LinkedAlternateVersions.ToList();
 218
 219        foreach (var item in items.Where(i => !i.Id.Equals(primaryVersion.Id)))
 220        {
 221            item.SetPrimaryVersionId(primaryVersion.Id.ToString("N", CultureInfo.InvariantCulture));
 222
 223            await item.UpdateToRepositoryAsync(ItemUpdateType.MetadataEdit, CancellationToken.None).ConfigureAwait(false
 224
 225            if (!alternateVersionsOfPrimary.Any(i => string.Equals(i.Path, item.Path, StringComparison.OrdinalIgnoreCase
 226            {
 227                alternateVersionsOfPrimary.Add(new LinkedChild
 228                {
 229                    Path = item.Path,
 230                    ItemId = item.Id
 231                });
 232            }
 233
 234            foreach (var linkedItem in item.LinkedAlternateVersions)
 235            {
 236                if (!alternateVersionsOfPrimary.Any(i => string.Equals(i.Path, linkedItem.Path, StringComparison.Ordinal
 237                {
 238                    alternateVersionsOfPrimary.Add(linkedItem);
 239                }
 240            }
 241
 242            if (item.LinkedAlternateVersions.Length > 0)
 243            {
 244                item.LinkedAlternateVersions = Array.Empty<LinkedChild>();
 245                await item.UpdateToRepositoryAsync(ItemUpdateType.MetadataEdit, CancellationToken.None).ConfigureAwait(f
 246            }
 247        }
 248
 249        primaryVersion.LinkedAlternateVersions = alternateVersionsOfPrimary.ToArray();
 250        await primaryVersion.UpdateToRepositoryAsync(ItemUpdateType.MetadataEdit, CancellationToken.None).ConfigureAwait
 251        return NoContent();
 252    }
 253
 254    /// <summary>
 255    /// Gets a video stream.
 256    /// </summary>
 257    /// <param name="itemId">The item id.</param>
 258    /// <param name="container">The video container. Possible values are: ts, webm, asf, wmv, ogv, mp4, m4v, mkv, mpeg, 
 259    /// <param name="static">Optional. If true, the original file will be streamed statically without any encoding. Use 
 260    /// <param name="params">The streaming parameters.</param>
 261    /// <param name="tag">The tag.</param>
 262    /// <param name="deviceProfileId">Optional. The dlna device profile id to utilize.</param>
 263    /// <param name="playSessionId">The play session id.</param>
 264    /// <param name="segmentContainer">The segment container.</param>
 265    /// <param name="segmentLength">The segment length.</param>
 266    /// <param name="minSegments">The minimum number of segments.</param>
 267    /// <param name="mediaSourceId">The media version id, if playing an alternate version.</param>
 268    /// <param name="deviceId">The device id of the client requesting. Used to stop encoding processes when needed.</par
 269    /// <param name="audioCodec">Optional. Specify an audio codec to encode to, e.g. mp3. If omitted the server will aut
 270    /// <param name="enableAutoStreamCopy">Whether or not to allow automatic stream copy if requested values match the o
 271    /// <param name="allowVideoStreamCopy">Whether or not to allow copying of the video stream url.</param>
 272    /// <param name="allowAudioStreamCopy">Whether or not to allow copying of the audio stream url.</param>
 273    /// <param name="breakOnNonKeyFrames">Optional. Whether to break on non key frames.</param>
 274    /// <param name="audioSampleRate">Optional. Specify a specific audio sample rate, e.g. 44100.</param>
 275    /// <param name="maxAudioBitDepth">Optional. The maximum audio bit depth.</param>
 276    /// <param name="audioBitRate">Optional. Specify an audio bitrate to encode to, e.g. 128000. If omitted this will be
 277    /// <param name="audioChannels">Optional. Specify a specific number of audio channels to encode to, e.g. 2.</param>
 278    /// <param name="maxAudioChannels">Optional. Specify a maximum number of audio channels to encode to, e.g. 2.</param
 279    /// <param name="profile">Optional. Specify a specific an encoder profile (varies by encoder), e.g. main, baseline, 
 280    /// <param name="level">Optional. Specify a level for the encoder profile (varies by encoder), e.g. 3, 3.1.</param>
 281    /// <param name="framerate">Optional. A specific video framerate to encode to, e.g. 23.976. Generally this should be
 282    /// <param name="maxFramerate">Optional. A specific maximum video framerate to encode to, e.g. 23.976. Generally thi
 283    /// <param name="copyTimestamps">Whether or not to copy timestamps when transcoding with an offset. Defaults to fals
 284    /// <param name="startTimeTicks">Optional. Specify a starting offset, in ticks. 1 tick = 10000 ms.</param>
 285    /// <param name="width">Optional. The fixed horizontal resolution of the encoded video.</param>
 286    /// <param name="height">Optional. The fixed vertical resolution of the encoded video.</param>
 287    /// <param name="maxWidth">Optional. The maximum horizontal resolution of the encoded video.</param>
 288    /// <param name="maxHeight">Optional. The maximum vertical resolution of the encoded video.</param>
 289    /// <param name="videoBitRate">Optional. Specify a video bitrate to encode to, e.g. 500000. If omitted this will be 
 290    /// <param name="subtitleStreamIndex">Optional. The index of the subtitle stream to use. If omitted no subtitles wil
 291    /// <param name="subtitleMethod">Optional. Specify the subtitle delivery method.</param>
 292    /// <param name="maxRefFrames">Optional.</param>
 293    /// <param name="maxVideoBitDepth">Optional. The maximum video bit depth.</param>
 294    /// <param name="requireAvc">Optional. Whether to require avc.</param>
 295    /// <param name="deInterlace">Optional. Whether to deinterlace the video.</param>
 296    /// <param name="requireNonAnamorphic">Optional. Whether to require a non anamorphic stream.</param>
 297    /// <param name="transcodingMaxAudioChannels">Optional. The maximum number of audio channels to transcode.</param>
 298    /// <param name="cpuCoreLimit">Optional. The limit of how many cpu cores to use.</param>
 299    /// <param name="liveStreamId">The live stream id.</param>
 300    /// <param name="enableMpegtsM2TsMode">Optional. Whether to enable the MpegtsM2Ts mode.</param>
 301    /// <param name="videoCodec">Optional. Specify a video codec to encode to, e.g. h264. If omitted the server will aut
 302    /// <param name="subtitleCodec">Optional. Specify a subtitle codec to encode to.</param>
 303    /// <param name="transcodeReasons">Optional. The transcoding reason.</param>
 304    /// <param name="audioStreamIndex">Optional. The index of the audio stream to use. If omitted the first audio stream
 305    /// <param name="videoStreamIndex">Optional. The index of the video stream to use. If omitted the first video stream
 306    /// <param name="context">Optional. The <see cref="EncodingContext"/>.</param>
 307    /// <param name="streamOptions">Optional. The streaming options.</param>
 308    /// <param name="enableAudioVbrEncoding">Optional. Whether to enable Audio Encoding.</param>
 309    /// <response code="200">Video stream returned.</response>
 310    /// <returns>A <see cref="FileResult"/> containing the audio file.</returns>
 311    [HttpGet("{itemId}/stream")]
 312    [HttpHead("{itemId}/stream", Name = "HeadVideoStream")]
 313    [ProducesResponseType(StatusCodes.Status200OK)]
 314    [ProducesVideoFile]
 315    public async Task<ActionResult> GetVideoStream(
 316        [FromRoute, Required] Guid itemId,
 317        [FromQuery] [RegularExpression(EncodingHelper.ContainerValidationRegex)] string? container,
 318        [FromQuery] bool? @static,
 319        [FromQuery] string? @params,
 320        [FromQuery] string? tag,
 321        [FromQuery, ParameterObsolete] string? deviceProfileId,
 322        [FromQuery] string? playSessionId,
 323        [FromQuery] [RegularExpression(EncodingHelper.ContainerValidationRegex)] string? segmentContainer,
 324        [FromQuery] int? segmentLength,
 325        [FromQuery] int? minSegments,
 326        [FromQuery] string? mediaSourceId,
 327        [FromQuery] string? deviceId,
 328        [FromQuery] [RegularExpression(EncodingHelper.ContainerValidationRegex)] string? audioCodec,
 329        [FromQuery] bool? enableAutoStreamCopy,
 330        [FromQuery] bool? allowVideoStreamCopy,
 331        [FromQuery] bool? allowAudioStreamCopy,
 332        [FromQuery] bool? breakOnNonKeyFrames,
 333        [FromQuery] int? audioSampleRate,
 334        [FromQuery] int? maxAudioBitDepth,
 335        [FromQuery] int? audioBitRate,
 336        [FromQuery] int? audioChannels,
 337        [FromQuery] int? maxAudioChannels,
 338        [FromQuery] string? profile,
 339        [FromQuery] [RegularExpression(EncodingHelper.LevelValidationRegex)] string? level,
 340        [FromQuery] float? framerate,
 341        [FromQuery] float? maxFramerate,
 342        [FromQuery] bool? copyTimestamps,
 343        [FromQuery] long? startTimeTicks,
 344        [FromQuery] int? width,
 345        [FromQuery] int? height,
 346        [FromQuery] int? maxWidth,
 347        [FromQuery] int? maxHeight,
 348        [FromQuery] int? videoBitRate,
 349        [FromQuery] int? subtitleStreamIndex,
 350        [FromQuery] SubtitleDeliveryMethod? subtitleMethod,
 351        [FromQuery] int? maxRefFrames,
 352        [FromQuery] int? maxVideoBitDepth,
 353        [FromQuery] bool? requireAvc,
 354        [FromQuery] bool? deInterlace,
 355        [FromQuery] bool? requireNonAnamorphic,
 356        [FromQuery] int? transcodingMaxAudioChannels,
 357        [FromQuery] int? cpuCoreLimit,
 358        [FromQuery] string? liveStreamId,
 359        [FromQuery] bool? enableMpegtsM2TsMode,
 360        [FromQuery] [RegularExpression(EncodingHelper.ContainerValidationRegex)] string? videoCodec,
 361        [FromQuery] [RegularExpression(EncodingHelper.ContainerValidationRegex)] string? subtitleCodec,
 362        [FromQuery] string? transcodeReasons,
 363        [FromQuery] int? audioStreamIndex,
 364        [FromQuery] int? videoStreamIndex,
 365        [FromQuery] EncodingContext? context,
 366        [FromQuery] Dictionary<string, string> streamOptions,
 367        [FromQuery] bool enableAudioVbrEncoding = true)
 368    {
 369        var isHeadRequest = Request.Method == System.Net.WebRequestMethods.Http.Head;
 370        // CTS lifecycle is managed internally.
 371        var cancellationTokenSource = new CancellationTokenSource();
 372        var streamingRequest = new VideoRequestDto
 373        {
 374            Id = itemId,
 375            Container = container,
 376            Static = @static ?? false,
 377            Params = @params,
 378            Tag = tag,
 379            PlaySessionId = playSessionId,
 380            SegmentContainer = segmentContainer,
 381            SegmentLength = segmentLength,
 382            MinSegments = minSegments,
 383            MediaSourceId = mediaSourceId,
 384            DeviceId = deviceId,
 385            AudioCodec = audioCodec,
 386            EnableAutoStreamCopy = enableAutoStreamCopy ?? true,
 387            AllowAudioStreamCopy = allowAudioStreamCopy ?? true,
 388            AllowVideoStreamCopy = allowVideoStreamCopy ?? true,
 389            BreakOnNonKeyFrames = breakOnNonKeyFrames ?? false,
 390            AudioSampleRate = audioSampleRate,
 391            MaxAudioChannels = maxAudioChannels,
 392            AudioBitRate = audioBitRate,
 393            MaxAudioBitDepth = maxAudioBitDepth,
 394            AudioChannels = audioChannels,
 395            Profile = profile,
 396            Level = level,
 397            Framerate = framerate,
 398            MaxFramerate = maxFramerate,
 399            CopyTimestamps = copyTimestamps ?? false,
 400            StartTimeTicks = startTimeTicks,
 401            Width = width,
 402            Height = height,
 403            MaxWidth = maxWidth,
 404            MaxHeight = maxHeight,
 405            VideoBitRate = videoBitRate,
 406            SubtitleStreamIndex = subtitleStreamIndex,
 407            SubtitleMethod = subtitleMethod ?? SubtitleDeliveryMethod.Encode,
 408            MaxRefFrames = maxRefFrames,
 409            MaxVideoBitDepth = maxVideoBitDepth,
 410            RequireAvc = requireAvc ?? false,
 411            DeInterlace = deInterlace ?? false,
 412            RequireNonAnamorphic = requireNonAnamorphic ?? false,
 413            TranscodingMaxAudioChannels = transcodingMaxAudioChannels,
 414            CpuCoreLimit = cpuCoreLimit,
 415            LiveStreamId = liveStreamId,
 416            EnableMpegtsM2TsMode = enableMpegtsM2TsMode ?? false,
 417            VideoCodec = videoCodec,
 418            SubtitleCodec = subtitleCodec,
 419            TranscodeReasons = transcodeReasons,
 420            AudioStreamIndex = audioStreamIndex,
 421            VideoStreamIndex = videoStreamIndex,
 422            Context = context ?? EncodingContext.Streaming,
 423            StreamOptions = streamOptions,
 424            EnableAudioVbrEncoding = enableAudioVbrEncoding
 425        };
 426
 427        var state = await StreamingHelpers.GetStreamingState(
 428                streamingRequest,
 429                HttpContext,
 430                _mediaSourceManager,
 431                _userManager,
 432                _libraryManager,
 433                _serverConfigurationManager,
 434                _mediaEncoder,
 435                _encodingHelper,
 436                _transcodeManager,
 437                _transcodingJobType,
 438                cancellationTokenSource.Token)
 439            .ConfigureAwait(false);
 440
 441        if (@static.HasValue && @static.Value && state.DirectStreamProvider is not null)
 442        {
 443            var liveStreamInfo = _mediaSourceManager.GetLiveStreamInfo(streamingRequest.LiveStreamId);
 444            if (liveStreamInfo is null)
 445            {
 446                return NotFound();
 447            }
 448
 449            var liveStream = new ProgressiveFileStream(liveStreamInfo.GetStream());
 450            // TODO (moved from MediaBrowser.Api): Don't hardcode contentType
 451            return File(liveStream, MimeTypes.GetMimeType("file.ts"));
 452        }
 453
 454        // Static remote stream
 455        if (@static.HasValue && @static.Value && state.InputProtocol == MediaProtocol.Http)
 456        {
 457            var httpClient = _httpClientFactory.CreateClient(NamedClient.Default);
 458            return await FileStreamResponseHelpers.GetStaticRemoteStreamResult(state, httpClient, HttpContext).Configure
 459        }
 460
 461        if (@static.HasValue && @static.Value && state.InputProtocol != MediaProtocol.File)
 462        {
 463            return BadRequest($"Input protocol {state.InputProtocol} cannot be streamed statically");
 464        }
 465
 466        // Static stream
 467        if (@static.HasValue && @static.Value && !(state.MediaSource.VideoType == VideoType.BluRay || state.MediaSource.
 468        {
 469            var contentType = state.GetMimeType("." + state.OutputContainer, false) ?? state.GetMimeType(state.MediaPath
 470
 471            if (state.MediaSource.IsInfiniteStream)
 472            {
 473                var liveStream = new ProgressiveFileStream(state.MediaPath, null, _transcodeManager);
 474                return File(liveStream, contentType);
 475            }
 476
 477            return FileStreamResponseHelpers.GetStaticFileResult(
 478                state.MediaPath,
 479                contentType);
 480        }
 481
 482        // Need to start ffmpeg (because media can't be returned directly)
 483        var encodingOptions = _serverConfigurationManager.GetEncodingOptions();
 484        var ffmpegCommandLineArguments = _encodingHelper.GetProgressiveVideoFullCommandLine(state, encodingOptions, Enco
 485        return await FileStreamResponseHelpers.GetTranscodedFile(
 486            state,
 487            isHeadRequest,
 488            HttpContext,
 489            _transcodeManager,
 490            ffmpegCommandLineArguments,
 491            _transcodingJobType,
 492            cancellationTokenSource).ConfigureAwait(false);
 493    }
 494
 495    /// <summary>
 496    /// Gets a video stream.
 497    /// </summary>
 498    /// <param name="itemId">The item id.</param>
 499    /// <param name="container">The video container. Possible values are: ts, webm, asf, wmv, ogv, mp4, m4v, mkv, mpeg, 
 500    /// <param name="static">Optional. If true, the original file will be streamed statically without any encoding. Use 
 501    /// <param name="params">The streaming parameters.</param>
 502    /// <param name="tag">The tag.</param>
 503    /// <param name="deviceProfileId">Optional. The dlna device profile id to utilize.</param>
 504    /// <param name="playSessionId">The play session id.</param>
 505    /// <param name="segmentContainer">The segment container.</param>
 506    /// <param name="segmentLength">The segment length.</param>
 507    /// <param name="minSegments">The minimum number of segments.</param>
 508    /// <param name="mediaSourceId">The media version id, if playing an alternate version.</param>
 509    /// <param name="deviceId">The device id of the client requesting. Used to stop encoding processes when needed.</par
 510    /// <param name="audioCodec">Optional. Specify an audio codec to encode to, e.g. mp3. If omitted the server will aut
 511    /// <param name="enableAutoStreamCopy">Whether or not to allow automatic stream copy if requested values match the o
 512    /// <param name="allowVideoStreamCopy">Whether or not to allow copying of the video stream url.</param>
 513    /// <param name="allowAudioStreamCopy">Whether or not to allow copying of the audio stream url.</param>
 514    /// <param name="breakOnNonKeyFrames">Optional. Whether to break on non key frames.</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.ContainerValidationRegex)] 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.ContainerValidationRegex)] string? segmentContainer,
 565        [FromQuery] int? segmentLength,
 566        [FromQuery] int? minSegments,
 567        [FromQuery] string? mediaSourceId,
 568        [FromQuery] string? deviceId,
 569        [FromQuery] [RegularExpression(EncodingHelper.ContainerValidationRegex)] string? audioCodec,
 570        [FromQuery] bool? enableAutoStreamCopy,
 571        [FromQuery] bool? allowVideoStreamCopy,
 572        [FromQuery] bool? allowAudioStreamCopy,
 573        [FromQuery] bool? breakOnNonKeyFrames,
 574        [FromQuery] int? audioSampleRate,
 575        [FromQuery] int? maxAudioBitDepth,
 576        [FromQuery] int? audioBitRate,
 577        [FromQuery] int? audioChannels,
 578        [FromQuery] int? maxAudioChannels,
 579        [FromQuery] string? profile,
 580        [FromQuery] [RegularExpression(EncodingHelper.LevelValidationRegex)] string? level,
 581        [FromQuery] float? framerate,
 582        [FromQuery] float? maxFramerate,
 583        [FromQuery] bool? copyTimestamps,
 584        [FromQuery] long? startTimeTicks,
 585        [FromQuery] int? width,
 586        [FromQuery] int? height,
 587        [FromQuery] int? maxWidth,
 588        [FromQuery] int? maxHeight,
 589        [FromQuery] int? videoBitRate,
 590        [FromQuery] int? subtitleStreamIndex,
 591        [FromQuery] SubtitleDeliveryMethod? subtitleMethod,
 592        [FromQuery] int? maxRefFrames,
 593        [FromQuery] int? maxVideoBitDepth,
 594        [FromQuery] bool? requireAvc,
 595        [FromQuery] bool? deInterlace,
 596        [FromQuery] bool? requireNonAnamorphic,
 597        [FromQuery] int? transcodingMaxAudioChannels,
 598        [FromQuery] int? cpuCoreLimit,
 599        [FromQuery] string? liveStreamId,
 600        [FromQuery] bool? enableMpegtsM2TsMode,
 601        [FromQuery] [RegularExpression(EncodingHelper.ContainerValidationRegex)] string? videoCodec,
 602        [FromQuery] [RegularExpression(EncodingHelper.ContainerValidationRegex)] string? subtitleCodec,
 603        [FromQuery] string? transcodeReasons,
 604        [FromQuery] int? audioStreamIndex,
 605        [FromQuery] int? videoStreamIndex,
 606        [FromQuery] EncodingContext? context,
 607        [FromQuery] Dictionary<string, string> streamOptions,
 608        [FromQuery] bool enableAudioVbrEncoding = true)
 609    {
 0610        return GetVideoStream(
 0611            itemId,
 0612            container,
 0613            @static,
 0614            @params,
 0615            tag,
 0616            deviceProfileId,
 0617            playSessionId,
 0618            segmentContainer,
 0619            segmentLength,
 0620            minSegments,
 0621            mediaSourceId,
 0622            deviceId,
 0623            audioCodec,
 0624            enableAutoStreamCopy,
 0625            allowVideoStreamCopy,
 0626            allowAudioStreamCopy,
 0627            breakOnNonKeyFrames,
 0628            audioSampleRate,
 0629            maxAudioBitDepth,
 0630            audioBitRate,
 0631            audioChannels,
 0632            maxAudioChannels,
 0633            profile,
 0634            level,
 0635            framerate,
 0636            maxFramerate,
 0637            copyTimestamps,
 0638            startTimeTicks,
 0639            width,
 0640            height,
 0641            maxWidth,
 0642            maxHeight,
 0643            videoBitRate,
 0644            subtitleStreamIndex,
 0645            subtitleMethod,
 0646            maxRefFrames,
 0647            maxVideoBitDepth,
 0648            requireAvc,
 0649            deInterlace,
 0650            requireNonAnamorphic,
 0651            transcodingMaxAudioChannels,
 0652            cpuCoreLimit,
 0653            liveStreamId,
 0654            enableMpegtsM2TsMode,
 0655            videoCodec,
 0656            subtitleCodec,
 0657            transcodeReasons,
 0658            audioStreamIndex,
 0659            videoStreamIndex,
 0660            context,
 0661            streamOptions,
 0662            enableAudioVbrEncoding);
 663    }
 664}

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>)
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.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)