mirror of
https://github.com/jellyfin/jellyfin.git
synced 2026-07-02 12:22:52 +01:00
support static trailer streaming
This commit is contained in:
@@ -56,6 +56,8 @@
|
||||
<Reference Include="Microsoft.CSharp" />
|
||||
<Reference Include="System.Data" />
|
||||
<Reference Include="System.Drawing" />
|
||||
<Reference Include="System.Net.Http" />
|
||||
<Reference Include="System.Net.Http.WebRequest" />
|
||||
<Reference Include="System.XML" />
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
@@ -82,6 +84,7 @@
|
||||
<Compile Include="Playback\Progressive\BaseProgressiveStreamingService.cs" />
|
||||
<Compile Include="Playback\BaseStreamingService.cs" />
|
||||
<Compile Include="Playback\Progressive\ProgressiveStreamWriter.cs" />
|
||||
<Compile Include="Playback\StaticRemoteStreamWriter.cs" />
|
||||
<Compile Include="Playback\StreamRequest.cs" />
|
||||
<Compile Include="Playback\StreamState.cs" />
|
||||
<Compile Include="Playback\Progressive\VideoService.cs" />
|
||||
|
||||
@@ -621,10 +621,27 @@ namespace MediaBrowser.Api.Playback
|
||||
/// <param name="item">The item.</param>
|
||||
/// <returns>System.String.</returns>
|
||||
protected string GetUserAgentParam(BaseItem item)
|
||||
{
|
||||
var useragent = GetUserAgent(item);
|
||||
|
||||
if (!string.IsNullOrEmpty(useragent))
|
||||
{
|
||||
return "-user-agent \"" + useragent + "\"";
|
||||
}
|
||||
|
||||
return string.Empty;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Gets the user agent.
|
||||
/// </summary>
|
||||
/// <param name="item">The item.</param>
|
||||
/// <returns>System.String.</returns>
|
||||
protected string GetUserAgent(BaseItem item)
|
||||
{
|
||||
if (item.Path.IndexOf("apple.com", StringComparison.OrdinalIgnoreCase) != -1)
|
||||
{
|
||||
return "-user-agent \"QuickTime/7.6.2\"";
|
||||
return "QuickTime/7.6.2";
|
||||
}
|
||||
|
||||
return string.Empty;
|
||||
|
||||
@@ -1,4 +1,7 @@
|
||||
using MediaBrowser.Api.Images;
|
||||
using System.Net;
|
||||
using System.Net.Cache;
|
||||
using System.Net.Http;
|
||||
using MediaBrowser.Api.Images;
|
||||
using MediaBrowser.Common.IO;
|
||||
using MediaBrowser.Common.MediaInfo;
|
||||
using MediaBrowser.Common.Net;
|
||||
@@ -188,6 +191,11 @@ namespace MediaBrowser.Api.Playback.Progressive
|
||||
|
||||
var responseHeaders = new Dictionary<string, string>();
|
||||
|
||||
if (request.Static && state.Item.LocationType == LocationType.Remote)
|
||||
{
|
||||
return GetStaticRemoteStreamResult(state.Item, responseHeaders, isHeadRequest).Result;
|
||||
}
|
||||
|
||||
var outputPath = GetOutputFilePath(state);
|
||||
var outputPathExists = File.Exists(outputPath);
|
||||
|
||||
@@ -209,6 +217,60 @@ namespace MediaBrowser.Api.Playback.Progressive
|
||||
return GetStreamResult(state, responseHeaders, isHeadRequest).Result;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Gets the static remote stream result.
|
||||
/// </summary>
|
||||
/// <param name="item">The item.</param>
|
||||
/// <param name="responseHeaders">The response headers.</param>
|
||||
/// <param name="isHeadRequest">if set to <c>true</c> [is head request].</param>
|
||||
/// <returns>Task{System.Object}.</returns>
|
||||
private async Task<object> GetStaticRemoteStreamResult(BaseItem item, Dictionary<string, string> responseHeaders, bool isHeadRequest)
|
||||
{
|
||||
responseHeaders["Accept-Ranges"] = "none";
|
||||
|
||||
var httpClient = new HttpClient(new WebRequestHandler
|
||||
{
|
||||
CachePolicy = new RequestCachePolicy(RequestCacheLevel.BypassCache),
|
||||
AutomaticDecompression = DecompressionMethods.None
|
||||
});
|
||||
|
||||
using (var message = new HttpRequestMessage(HttpMethod.Get, item.Path))
|
||||
{
|
||||
var useragent = GetUserAgent(item);
|
||||
|
||||
if (!string.IsNullOrEmpty(useragent))
|
||||
{
|
||||
message.Headers.Add("User-Agent", useragent);
|
||||
}
|
||||
|
||||
var response = await httpClient.SendAsync(message, HttpCompletionOption.ResponseHeadersRead).ConfigureAwait(false);
|
||||
|
||||
response.EnsureSuccessStatusCode();
|
||||
|
||||
var contentType = response.Content.Headers.ContentType.MediaType;
|
||||
|
||||
// Headers only
|
||||
if (isHeadRequest)
|
||||
{
|
||||
response.Dispose();
|
||||
|
||||
return ResultFactory.GetResult(null, contentType, responseHeaders);
|
||||
}
|
||||
|
||||
var result = new StaticRemoteStreamWriter(response, httpClient);
|
||||
|
||||
result.Options["Content-Type"] = contentType;
|
||||
|
||||
// Add the response headers to the result object
|
||||
foreach (var header in responseHeaders)
|
||||
{
|
||||
result.Options[header.Key] = header.Value;
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Gets the album art response.
|
||||
/// </summary>
|
||||
|
||||
75
MediaBrowser.Api/Playback/StaticRemoteStreamWriter.cs
Normal file
75
MediaBrowser.Api/Playback/StaticRemoteStreamWriter.cs
Normal file
@@ -0,0 +1,75 @@
|
||||
using ServiceStack.Service;
|
||||
using ServiceStack.ServiceHost;
|
||||
using System.Collections.Generic;
|
||||
using System.IO;
|
||||
using System.Net.Http;
|
||||
using System.Threading.Tasks;
|
||||
|
||||
namespace MediaBrowser.Api.Playback
|
||||
{
|
||||
/// <summary>
|
||||
/// Class StaticRemoteStreamWriter
|
||||
/// </summary>
|
||||
public class StaticRemoteStreamWriter : IStreamWriter, IHasOptions
|
||||
{
|
||||
/// <summary>
|
||||
/// The _input stream
|
||||
/// </summary>
|
||||
private readonly HttpResponseMessage _msg;
|
||||
|
||||
private readonly HttpClient _client;
|
||||
|
||||
/// <summary>
|
||||
/// The _options
|
||||
/// </summary>
|
||||
private readonly IDictionary<string, string> _options = new Dictionary<string, string>();
|
||||
|
||||
/// <summary>
|
||||
/// Initializes a new instance of the <see cref="StaticRemoteStreamWriter"/> class.
|
||||
/// </summary>
|
||||
public StaticRemoteStreamWriter(HttpResponseMessage msg, HttpClient client)
|
||||
{
|
||||
_msg = msg;
|
||||
_client = client;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Gets the options.
|
||||
/// </summary>
|
||||
/// <value>The options.</value>
|
||||
public IDictionary<string, string> Options
|
||||
{
|
||||
get { return _options; }
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Writes to.
|
||||
/// </summary>
|
||||
/// <param name="responseStream">The response stream.</param>
|
||||
public void WriteTo(Stream responseStream)
|
||||
{
|
||||
var task = WriteToAsync(responseStream);
|
||||
|
||||
Task.WaitAll(task);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Writes to async.
|
||||
/// </summary>
|
||||
/// <param name="responseStream">The response stream.</param>
|
||||
/// <returns>Task.</returns>
|
||||
public async Task WriteToAsync(Stream responseStream)
|
||||
{
|
||||
using (_client)
|
||||
{
|
||||
using (_msg)
|
||||
{
|
||||
using (var input = await _msg.Content.ReadAsStreamAsync().ConfigureAwait(false))
|
||||
{
|
||||
await input.CopyToAsync(responseStream).ConfigureAwait(false);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -135,7 +135,7 @@ namespace MediaBrowser.Api.UserLibrary
|
||||
{
|
||||
if (!string.IsNullOrEmpty(request.NameStartsWithOrGreater))
|
||||
{
|
||||
items = items.Where(i => string.Compare(request.NameStartsWithOrGreater, i.Name, StringComparison.OrdinalIgnoreCase) < 1);
|
||||
items = items.Where(i => string.Compare(request.NameStartsWithOrGreater, i.Name, StringComparison.CurrentCultureIgnoreCase) < 1);
|
||||
}
|
||||
|
||||
var filters = request.GetFilters().ToList();
|
||||
|
||||
@@ -456,7 +456,7 @@ namespace MediaBrowser.Api.UserLibrary
|
||||
|
||||
if (!string.IsNullOrEmpty(request.NameStartsWithOrGreater))
|
||||
{
|
||||
items = items.Where(i => string.Compare(request.NameStartsWithOrGreater, i.SortName, StringComparison.OrdinalIgnoreCase) < 1);
|
||||
items = items.Where(i => string.Compare(request.NameStartsWithOrGreater, i.SortName, StringComparison.CurrentCultureIgnoreCase) < 1);
|
||||
}
|
||||
|
||||
// Filter by Series Status
|
||||
|
||||
Reference in New Issue
Block a user