< 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: 93
Coverable lines: 93
Total lines: 665
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

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();
 0114        dtoOptions = dtoOptions.AddClientFields(User);
 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    {
 145        var item = _libraryManager.GetItemById<Video>(itemId, User.GetUserId());
 146        if (item is null)
 147        {
 148            return NotFound();
 149        }
 150
 151        if (item.LinkedAlternateVersions.Length == 0)
 152        {
 153            item = _libraryManager.GetItemById<Video>(Guid.Parse(item.PrimaryVersionId));
 154        }
 155
 156        if (item is null)
 157        {
 158            return NotFound();
 159        }
 160
 161        foreach (var link in item.GetLinkedAlternateVersions())
 162        {
 163            link.SetPrimaryVersionId(null);
 164            link.LinkedAlternateVersions = Array.Empty<LinkedChild>();
 165
 166            await link.UpdateToRepositoryAsync(ItemUpdateType.MetadataEdit, CancellationToken.None).ConfigureAwait(false
 167        }
 168
 169        item.LinkedAlternateVersions = Array.Empty<LinkedChild>();
 170        item.SetPrimaryVersionId(null);
 171        await item.UpdateToRepositoryAsync(ItemUpdateType.MetadataEdit, CancellationToken.None).ConfigureAwait(false);
 172
 173        return NoContent();
 174    }
 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(CommaDelimitedArrayModelBinde
 188    {
 189        var userId = User.GetUserId();
 190        var items = ids
 191            .Select(i => _libraryManager.GetItemById<BaseItem>(i, userId))
 192            .OfType<Video>()
 193            .OrderBy(i => i.Id)
 194            .ToList();
 195
 196        if (items.Count < 2)
 197        {
 198            return BadRequest("Please supply at least two videos to merge.");
 199        }
 200
 201        var primaryVersion = items.FirstOrDefault(i => i.MediaSourceCount > 1 && string.IsNullOrEmpty(i.PrimaryVersionId
 202        if (primaryVersion is null)
 203        {
 204            primaryVersion = items
 205                .OrderBy(i =>
 206                {
 207                    if (i.Video3DFormat.HasValue || i.VideoType != VideoType.VideoFile)
 208                    {
 209                        return 1;
 210                    }
 211
 212                    return 0;
 213                })
 214                .ThenByDescending(i => i.GetDefaultVideoStream()?.Width ?? 0)
 215                .First();
 216        }
 217
 218        var alternateVersionsOfPrimary = primaryVersion.LinkedAlternateVersions.ToList();
 219
 220        foreach (var item in items.Where(i => !i.Id.Equals(primaryVersion.Id)))
 221        {
 222            item.SetPrimaryVersionId(primaryVersion.Id.ToString("N", CultureInfo.InvariantCulture));
 223
 224            await item.UpdateToRepositoryAsync(ItemUpdateType.MetadataEdit, CancellationToken.None).ConfigureAwait(false
 225
 226            if (!alternateVersionsOfPrimary.Any(i => string.Equals(i.Path, item.Path, StringComparison.OrdinalIgnoreCase
 227            {
 228                alternateVersionsOfPrimary.Add(new LinkedChild
 229                {
 230                    Path = item.Path,
 231                    ItemId = item.Id
 232                });
 233            }
 234
 235            foreach (var linkedItem in item.LinkedAlternateVersions)
 236            {
 237                if (!alternateVersionsOfPrimary.Any(i => string.Equals(i.Path, linkedItem.Path, StringComparison.Ordinal
 238                {
 239                    alternateVersionsOfPrimary.Add(linkedItem);
 240                }
 241            }
 242
 243            if (item.LinkedAlternateVersions.Length > 0)
 244            {
 245                item.LinkedAlternateVersions = Array.Empty<LinkedChild>();
 246                await item.UpdateToRepositoryAsync(ItemUpdateType.MetadataEdit, CancellationToken.None).ConfigureAwait(f
 247            }
 248        }
 249
 250        primaryVersion.LinkedAlternateVersions = alternateVersionsOfPrimary.ToArray();
 251        await primaryVersion.UpdateToRepositoryAsync(ItemUpdateType.MetadataEdit, CancellationToken.None).ConfigureAwait
 252        return NoContent();
 253    }
 254
 255    /// <summary>
 256    /// Gets a video stream.
 257    /// </summary>
 258    /// <param name="itemId">The item id.</param>
 259    /// <param name="container">The video container. Possible values are: ts, webm, asf, wmv, ogv, mp4, m4v, mkv, mpeg, 
 260    /// <param name="static">Optional. If true, the original file will be streamed statically without any encoding. Use 
 261    /// <param name="params">The streaming parameters.</param>
 262    /// <param name="tag">The tag.</param>
 263    /// <param name="deviceProfileId">Optional. The dlna device profile id to utilize.</param>
 264    /// <param name="playSessionId">The play session id.</param>
 265    /// <param name="segmentContainer">The segment container.</param>
 266    /// <param name="segmentLength">The segment length.</param>
 267    /// <param name="minSegments">The minimum number of segments.</param>
 268    /// <param name="mediaSourceId">The media version id, if playing an alternate version.</param>
 269    /// <param name="deviceId">The device id of the client requesting. Used to stop encoding processes when needed.</par
 270    /// <param name="audioCodec">Optional. Specify an audio codec to encode to, e.g. mp3. If omitted the server will aut
 271    /// <param name="enableAutoStreamCopy">Whether or not to allow automatic stream copy if requested values match the o
 272    /// <param name="allowVideoStreamCopy">Whether or not to allow copying of the video stream url.</param>
 273    /// <param name="allowAudioStreamCopy">Whether or not to allow copying of the audio stream url.</param>
 274    /// <param name="breakOnNonKeyFrames">Optional. Whether to break on non key frames.</param>
 275    /// <param name="audioSampleRate">Optional. Specify a specific audio sample rate, e.g. 44100.</param>
 276    /// <param name="maxAudioBitDepth">Optional. The maximum audio bit depth.</param>
 277    /// <param name="audioBitRate">Optional. Specify an audio bitrate to encode to, e.g. 128000. If omitted this will be
 278    /// <param name="audioChannels">Optional. Specify a specific number of audio channels to encode to, e.g. 2.</param>
 279    /// <param name="maxAudioChannels">Optional. Specify a maximum number of audio channels to encode to, e.g. 2.</param
 280    /// <param name="profile">Optional. Specify a specific an encoder profile (varies by encoder), e.g. main, baseline, 
 281    /// <param name="level">Optional. Specify a level for the encoder profile (varies by encoder), e.g. 3, 3.1.</param>
 282    /// <param name="framerate">Optional. A specific video framerate to encode to, e.g. 23.976. Generally this should be
 283    /// <param name="maxFramerate">Optional. A specific maximum video framerate to encode to, e.g. 23.976. Generally thi
 284    /// <param name="copyTimestamps">Whether or not to copy timestamps when transcoding with an offset. Defaults to fals
 285    /// <param name="startTimeTicks">Optional. Specify a starting offset, in ticks. 1 tick = 10000 ms.</param>
 286    /// <param name="width">Optional. The fixed horizontal resolution of the encoded video.</param>
 287    /// <param name="height">Optional. The fixed vertical resolution of the encoded video.</param>
 288    /// <param name="maxWidth">Optional. The maximum horizontal resolution of the encoded video.</param>
 289    /// <param name="maxHeight">Optional. The maximum vertical resolution of the encoded video.</param>
 290    /// <param name="videoBitRate">Optional. Specify a video bitrate to encode to, e.g. 500000. If omitted this will be 
 291    /// <param name="subtitleStreamIndex">Optional. The index of the subtitle stream to use. If omitted no subtitles wil
 292    /// <param name="subtitleMethod">Optional. Specify the subtitle delivery method.</param>
 293    /// <param name="maxRefFrames">Optional.</param>
 294    /// <param name="maxVideoBitDepth">Optional. The maximum video bit depth.</param>
 295    /// <param name="requireAvc">Optional. Whether to require avc.</param>
 296    /// <param name="deInterlace">Optional. Whether to deinterlace the video.</param>
 297    /// <param name="requireNonAnamorphic">Optional. Whether to require a non anamorphic stream.</param>
 298    /// <param name="transcodingMaxAudioChannels">Optional. The maximum number of audio channels to transcode.</param>
 299    /// <param name="cpuCoreLimit">Optional. The limit of how many cpu cores to use.</param>
 300    /// <param name="liveStreamId">The live stream id.</param>
 301    /// <param name="enableMpegtsM2TsMode">Optional. Whether to enable the MpegtsM2Ts mode.</param>
 302    /// <param name="videoCodec">Optional. Specify a video codec to encode to, e.g. h264. If omitted the server will aut
 303    /// <param name="subtitleCodec">Optional. Specify a subtitle codec to encode to.</param>
 304    /// <param name="transcodeReasons">Optional. The transcoding reason.</param>
 305    /// <param name="audioStreamIndex">Optional. The index of the audio stream to use. If omitted the first audio stream
 306    /// <param name="videoStreamIndex">Optional. The index of the video stream to use. If omitted the first video stream
 307    /// <param name="context">Optional. The <see cref="EncodingContext"/>.</param>
 308    /// <param name="streamOptions">Optional. The streaming options.</param>
 309    /// <param name="enableAudioVbrEncoding">Optional. Whether to enable Audio Encoding.</param>
 310    /// <response code="200">Video stream returned.</response>
 311    /// <returns>A <see cref="FileResult"/> containing the audio file.</returns>
 312    [HttpGet("{itemId}/stream")]
 313    [HttpHead("{itemId}/stream", Name = "HeadVideoStream")]
 314    [ProducesResponseType(StatusCodes.Status200OK)]
 315    [ProducesVideoFile]
 316    public async Task<ActionResult> GetVideoStream(
 317        [FromRoute, Required] Guid itemId,
 318        [FromQuery] [RegularExpression(EncodingHelper.ValidationRegex)] string? container,
 319        [FromQuery] bool? @static,
 320        [FromQuery] string? @params,
 321        [FromQuery] string? tag,
 322        [FromQuery, ParameterObsolete] string? deviceProfileId,
 323        [FromQuery] string? playSessionId,
 324        [FromQuery] [RegularExpression(EncodingHelper.ValidationRegex)] string? segmentContainer,
 325        [FromQuery] int? segmentLength,
 326        [FromQuery] int? minSegments,
 327        [FromQuery] string? mediaSourceId,
 328        [FromQuery] string? deviceId,
 329        [FromQuery] [RegularExpression(EncodingHelper.ValidationRegex)] string? audioCodec,
 330        [FromQuery] bool? enableAutoStreamCopy,
 331        [FromQuery] bool? allowVideoStreamCopy,
 332        [FromQuery] bool? allowAudioStreamCopy,
 333        [FromQuery] bool? breakOnNonKeyFrames,
 334        [FromQuery] int? audioSampleRate,
 335        [FromQuery] int? maxAudioBitDepth,
 336        [FromQuery] int? audioBitRate,
 337        [FromQuery] int? audioChannels,
 338        [FromQuery] int? maxAudioChannels,
 339        [FromQuery] string? profile,
 340        [FromQuery] string? level,
 341        [FromQuery] float? framerate,
 342        [FromQuery] float? maxFramerate,
 343        [FromQuery] bool? copyTimestamps,
 344        [FromQuery] long? startTimeTicks,
 345        [FromQuery] int? width,
 346        [FromQuery] int? height,
 347        [FromQuery] int? maxWidth,
 348        [FromQuery] int? maxHeight,
 349        [FromQuery] int? videoBitRate,
 350        [FromQuery] int? subtitleStreamIndex,
 351        [FromQuery] SubtitleDeliveryMethod? subtitleMethod,
 352        [FromQuery] int? maxRefFrames,
 353        [FromQuery] int? maxVideoBitDepth,
 354        [FromQuery] bool? requireAvc,
 355        [FromQuery] bool? deInterlace,
 356        [FromQuery] bool? requireNonAnamorphic,
 357        [FromQuery] int? transcodingMaxAudioChannels,
 358        [FromQuery] int? cpuCoreLimit,
 359        [FromQuery] string? liveStreamId,
 360        [FromQuery] bool? enableMpegtsM2TsMode,
 361        [FromQuery] [RegularExpression(EncodingHelper.ValidationRegex)] string? videoCodec,
 362        [FromQuery] [RegularExpression(EncodingHelper.ValidationRegex)] string? subtitleCodec,
 363        [FromQuery] string? transcodeReasons,
 364        [FromQuery] int? audioStreamIndex,
 365        [FromQuery] int? videoStreamIndex,
 366        [FromQuery] EncodingContext? context,
 367        [FromQuery] Dictionary<string, string> streamOptions,
 368        [FromQuery] bool enableAudioVbrEncoding = true)
 369    {
 370        var isHeadRequest = Request.Method == System.Net.WebRequestMethods.Http.Head;
 371        // CTS lifecycle is managed internally.
 372        var cancellationTokenSource = new CancellationTokenSource();
 373        var streamingRequest = new VideoRequestDto
 374        {
 375            Id = itemId,
 376            Container = container,
 377            Static = @static ?? false,
 378            Params = @params,
 379            Tag = tag,
 380            PlaySessionId = playSessionId,
 381            SegmentContainer = segmentContainer,
 382            SegmentLength = segmentLength,
 383            MinSegments = minSegments,
 384            MediaSourceId = mediaSourceId,
 385            DeviceId = deviceId,
 386            AudioCodec = audioCodec,
 387            EnableAutoStreamCopy = enableAutoStreamCopy ?? true,
 388            AllowAudioStreamCopy = allowAudioStreamCopy ?? true,
 389            AllowVideoStreamCopy = allowVideoStreamCopy ?? true,
 390            BreakOnNonKeyFrames = breakOnNonKeyFrames ?? false,
 391            AudioSampleRate = audioSampleRate,
 392            MaxAudioChannels = maxAudioChannels,
 393            AudioBitRate = audioBitRate,
 394            MaxAudioBitDepth = maxAudioBitDepth,
 395            AudioChannels = audioChannels,
 396            Profile = profile,
 397            Level = level,
 398            Framerate = framerate,
 399            MaxFramerate = maxFramerate,
 400            CopyTimestamps = copyTimestamps ?? false,
 401            StartTimeTicks = startTimeTicks,
 402            Width = width,
 403            Height = height,
 404            MaxWidth = maxWidth,
 405            MaxHeight = maxHeight,
 406            VideoBitRate = videoBitRate,
 407            SubtitleStreamIndex = subtitleStreamIndex,
 408            SubtitleMethod = subtitleMethod ?? SubtitleDeliveryMethod.Encode,
 409            MaxRefFrames = maxRefFrames,
 410            MaxVideoBitDepth = maxVideoBitDepth,
 411            RequireAvc = requireAvc ?? false,
 412            DeInterlace = deInterlace ?? false,
 413            RequireNonAnamorphic = requireNonAnamorphic ?? false,
 414            TranscodingMaxAudioChannels = transcodingMaxAudioChannels,
 415            CpuCoreLimit = cpuCoreLimit,
 416            LiveStreamId = liveStreamId,
 417            EnableMpegtsM2TsMode = enableMpegtsM2TsMode ?? false,
 418            VideoCodec = videoCodec,
 419            SubtitleCodec = subtitleCodec,
 420            TranscodeReasons = transcodeReasons,
 421            AudioStreamIndex = audioStreamIndex,
 422            VideoStreamIndex = videoStreamIndex,
 423            Context = context ?? EncodingContext.Streaming,
 424            StreamOptions = streamOptions,
 425            EnableAudioVbrEncoding = enableAudioVbrEncoding
 426        };
 427
 428        var state = await StreamingHelpers.GetStreamingState(
 429                streamingRequest,
 430                HttpContext,
 431                _mediaSourceManager,
 432                _userManager,
 433                _libraryManager,
 434                _serverConfigurationManager,
 435                _mediaEncoder,
 436                _encodingHelper,
 437                _transcodeManager,
 438                _transcodingJobType,
 439                cancellationTokenSource.Token)
 440            .ConfigureAwait(false);
 441
 442        if (@static.HasValue && @static.Value && state.DirectStreamProvider is not null)
 443        {
 444            var liveStreamInfo = _mediaSourceManager.GetLiveStreamInfo(streamingRequest.LiveStreamId);
 445            if (liveStreamInfo is null)
 446            {
 447                return NotFound();
 448            }
 449
 450            var liveStream = new ProgressiveFileStream(liveStreamInfo.GetStream());
 451            // TODO (moved from MediaBrowser.Api): Don't hardcode contentType
 452            return File(liveStream, MimeTypes.GetMimeType("file.ts"));
 453        }
 454
 455        // Static remote stream
 456        if (@static.HasValue && @static.Value && state.InputProtocol == MediaProtocol.Http)
 457        {
 458            var httpClient = _httpClientFactory.CreateClient(NamedClient.Default);
 459            return await FileStreamResponseHelpers.GetStaticRemoteStreamResult(state, httpClient, HttpContext).Configure
 460        }
 461
 462        if (@static.HasValue && @static.Value && state.InputProtocol != MediaProtocol.File)
 463        {
 464            return BadRequest($"Input protocol {state.InputProtocol} cannot be streamed statically");
 465        }
 466
 467        // Static stream
 468        if (@static.HasValue && @static.Value && !(state.MediaSource.VideoType == VideoType.BluRay || state.MediaSource.
 469        {
 470            var contentType = state.GetMimeType("." + state.OutputContainer, false) ?? state.GetMimeType(state.MediaPath
 471
 472            if (state.MediaSource.IsInfiniteStream)
 473            {
 474                var liveStream = new ProgressiveFileStream(state.MediaPath, null, _transcodeManager);
 475                return File(liveStream, contentType);
 476            }
 477
 478            return FileStreamResponseHelpers.GetStaticFileResult(
 479                state.MediaPath,
 480                contentType);
 481        }
 482
 483        // Need to start ffmpeg (because media can't be returned directly)
 484        var encodingOptions = _serverConfigurationManager.GetEncodingOptions();
 485        var ffmpegCommandLineArguments = _encodingHelper.GetProgressiveVideoFullCommandLine(state, encodingOptions, Enco
 486        return await FileStreamResponseHelpers.GetTranscodedFile(
 487            state,
 488            isHeadRequest,
 489            HttpContext,
 490            _transcodeManager,
 491            ffmpegCommandLineArguments,
 492            _transcodingJobType,
 493            cancellationTokenSource).ConfigureAwait(false);
 494    }
 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="breakOnNonKeyFrames">Optional. Whether to break on non key frames.</param>
 516    /// <param name="audioSampleRate">Optional. Specify a specific audio sample rate, e.g. 44100.</param>
 517    /// <param name="maxAudioBitDepth">Optional. The maximum audio bit depth.</param>
 518    /// <param name="audioBitRate">Optional. Specify an audio bitrate to encode to, e.g. 128000. If omitted this will be
 519    /// <param name="audioChannels">Optional. Specify a specific number of audio channels to encode to, e.g. 2.</param>
 520    /// <param name="maxAudioChannels">Optional. Specify a maximum number of audio channels to encode to, e.g. 2.</param
 521    /// <param name="profile">Optional. Specify a specific an encoder profile (varies by encoder), e.g. main, baseline, 
 522    /// <param name="level">Optional. Specify a level for the encoder profile (varies by encoder), e.g. 3, 3.1.</param>
 523    /// <param name="framerate">Optional. A specific video framerate to encode to, e.g. 23.976. Generally this should be
 524    /// <param name="maxFramerate">Optional. A specific maximum video framerate to encode to, e.g. 23.976. Generally thi
 525    /// <param name="copyTimestamps">Whether or not to copy timestamps when transcoding with an offset. Defaults to fals
 526    /// <param name="startTimeTicks">Optional. Specify a starting offset, in ticks. 1 tick = 10000 ms.</param>
 527    /// <param name="width">Optional. The fixed horizontal resolution of the encoded video.</param>
 528    /// <param name="height">Optional. The fixed vertical resolution of the encoded video.</param>
 529    /// <param name="maxWidth">Optional. The maximum horizontal resolution of the encoded video.</param>
 530    /// <param name="maxHeight">Optional. The maximum vertical resolution of the encoded video.</param>
 531    /// <param name="videoBitRate">Optional. Specify a video bitrate to encode to, e.g. 500000. If omitted this will be 
 532    /// <param name="subtitleStreamIndex">Optional. The index of the subtitle stream to use. If omitted no subtitles wil
 533    /// <param name="subtitleMethod">Optional. Specify the subtitle delivery method.</param>
 534    /// <param name="maxRefFrames">Optional.</param>
 535    /// <param name="maxVideoBitDepth">Optional. The maximum video bit depth.</param>
 536    /// <param name="requireAvc">Optional. Whether to require avc.</param>
 537    /// <param name="deInterlace">Optional. Whether to deinterlace the video.</param>
 538    /// <param name="requireNonAnamorphic">Optional. Whether to require a non anamorphic stream.</param>
 539    /// <param name="transcodingMaxAudioChannels">Optional. The maximum number of audio channels to transcode.</param>
 540    /// <param name="cpuCoreLimit">Optional. The limit of how many cpu cores to use.</param>
 541    /// <param name="liveStreamId">The live stream id.</param>
 542    /// <param name="enableMpegtsM2TsMode">Optional. Whether to enable the MpegtsM2Ts mode.</param>
 543    /// <param name="videoCodec">Optional. Specify a video codec to encode to, e.g. h264. If omitted the server will aut
 544    /// <param name="subtitleCodec">Optional. Specify a subtitle codec to encode to.</param>
 545    /// <param name="transcodeReasons">Optional. The transcoding reason.</param>
 546    /// <param name="audioStreamIndex">Optional. The index of the audio stream to use. If omitted the first audio stream
 547    /// <param name="videoStreamIndex">Optional. The index of the video stream to use. If omitted the first video stream
 548    /// <param name="context">Optional. The <see cref="EncodingContext"/>.</param>
 549    /// <param name="streamOptions">Optional. The streaming options.</param>
 550    /// <param name="enableAudioVbrEncoding">Optional. Whether to enable Audio Encoding.</param>
 551    /// <response code="200">Video stream returned.</response>
 552    /// <returns>A <see cref="FileResult"/> containing the audio file.</returns>
 553    [HttpGet("{itemId}/stream.{container}")]
 554    [HttpHead("{itemId}/stream.{container}", Name = "HeadVideoStreamByContainer")]
 555    [ProducesResponseType(StatusCodes.Status200OK)]
 556    [ProducesVideoFile]
 557    public Task<ActionResult> GetVideoStreamByContainer(
 558        [FromRoute, Required] Guid itemId,
 559        [FromRoute, Required] string container,
 560        [FromQuery] bool? @static,
 561        [FromQuery] string? @params,
 562        [FromQuery] string? tag,
 563        [FromQuery] string? deviceProfileId,
 564        [FromQuery] string? playSessionId,
 565        [FromQuery] [RegularExpression(EncodingHelper.ValidationRegex)] string? segmentContainer,
 566        [FromQuery] int? segmentLength,
 567        [FromQuery] int? minSegments,
 568        [FromQuery] string? mediaSourceId,
 569        [FromQuery] string? deviceId,
 570        [FromQuery] [RegularExpression(EncodingHelper.ValidationRegex)] string? audioCodec,
 571        [FromQuery] bool? enableAutoStreamCopy,
 572        [FromQuery] bool? allowVideoStreamCopy,
 573        [FromQuery] bool? allowAudioStreamCopy,
 574        [FromQuery] bool? breakOnNonKeyFrames,
 575        [FromQuery] int? audioSampleRate,
 576        [FromQuery] int? maxAudioBitDepth,
 577        [FromQuery] int? audioBitRate,
 578        [FromQuery] int? audioChannels,
 579        [FromQuery] int? maxAudioChannels,
 580        [FromQuery] string? profile,
 581        [FromQuery] string? level,
 582        [FromQuery] float? framerate,
 583        [FromQuery] float? maxFramerate,
 584        [FromQuery] bool? copyTimestamps,
 585        [FromQuery] long? startTimeTicks,
 586        [FromQuery] int? width,
 587        [FromQuery] int? height,
 588        [FromQuery] int? maxWidth,
 589        [FromQuery] int? maxHeight,
 590        [FromQuery] int? videoBitRate,
 591        [FromQuery] int? subtitleStreamIndex,
 592        [FromQuery] SubtitleDeliveryMethod? subtitleMethod,
 593        [FromQuery] int? maxRefFrames,
 594        [FromQuery] int? maxVideoBitDepth,
 595        [FromQuery] bool? requireAvc,
 596        [FromQuery] bool? deInterlace,
 597        [FromQuery] bool? requireNonAnamorphic,
 598        [FromQuery] int? transcodingMaxAudioChannels,
 599        [FromQuery] int? cpuCoreLimit,
 600        [FromQuery] string? liveStreamId,
 601        [FromQuery] bool? enableMpegtsM2TsMode,
 602        [FromQuery] [RegularExpression(EncodingHelper.ValidationRegex)] string? videoCodec,
 603        [FromQuery] [RegularExpression(EncodingHelper.ValidationRegex)] string? subtitleCodec,
 604        [FromQuery] string? transcodeReasons,
 605        [FromQuery] int? audioStreamIndex,
 606        [FromQuery] int? videoStreamIndex,
 607        [FromQuery] EncodingContext? context,
 608        [FromQuery] Dictionary<string, string> streamOptions,
 609        [FromQuery] bool enableAudioVbrEncoding = true)
 610    {
 0611        return GetVideoStream(
 0612            itemId,
 0613            container,
 0614            @static,
 0615            @params,
 0616            tag,
 0617            deviceProfileId,
 0618            playSessionId,
 0619            segmentContainer,
 0620            segmentLength,
 0621            minSegments,
 0622            mediaSourceId,
 0623            deviceId,
 0624            audioCodec,
 0625            enableAutoStreamCopy,
 0626            allowVideoStreamCopy,
 0627            allowAudioStreamCopy,
 0628            breakOnNonKeyFrames,
 0629            audioSampleRate,
 0630            maxAudioBitDepth,
 0631            audioBitRate,
 0632            audioChannels,
 0633            maxAudioChannels,
 0634            profile,
 0635            level,
 0636            framerate,
 0637            maxFramerate,
 0638            copyTimestamps,
 0639            startTimeTicks,
 0640            width,
 0641            height,
 0642            maxWidth,
 0643            maxHeight,
 0644            videoBitRate,
 0645            subtitleStreamIndex,
 0646            subtitleMethod,
 0647            maxRefFrames,
 0648            maxVideoBitDepth,
 0649            requireAvc,
 0650            deInterlace,
 0651            requireNonAnamorphic,
 0652            transcodingMaxAudioChannels,
 0653            cpuCoreLimit,
 0654            liveStreamId,
 0655            enableMpegtsM2TsMode,
 0656            videoCodec,
 0657            subtitleCodec,
 0658            transcodeReasons,
 0659            audioStreamIndex,
 0660            videoStreamIndex,
 0661            context,
 0662            streamOptions,
 0663            enableAudioVbrEncoding);
 664    }
 665}

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)