Skip to content

Commit

Permalink
switch to subtitle filter
Browse files Browse the repository at this point in the history
  • Loading branch information
LukePulverenti committed Jun 10, 2014
1 parent b89270f commit 67ae275
Show file tree
Hide file tree
Showing 31 changed files with 250 additions and 428 deletions.
3 changes: 1 addition & 2 deletions MediaBrowser.Api/LiveTv/LiveTvService.cs
Original file line number Diff line number Diff line change
@@ -1,5 +1,4 @@
using MediaBrowser.Controller.Dto;
using MediaBrowser.Controller.Library;
using MediaBrowser.Controller.Library;
using MediaBrowser.Controller.LiveTv;
using MediaBrowser.Model.Dto;
using MediaBrowser.Model.Entities;
Expand Down
110 changes: 23 additions & 87 deletions MediaBrowser.Api/Playback/BaseStreamingService.cs
Original file line number Diff line number Diff line change
Expand Up @@ -101,9 +101,9 @@ protected BaseStreamingService(IServerConfigurationManager serverConfig, IUserMa
/// </summary>
/// <param name="outputPath">The output path.</param>
/// <param name="state">The state.</param>
/// <param name="performSubtitleConversions">if set to <c>true</c> [perform subtitle conversions].</param>
/// <param name="isEncoding">if set to <c>true</c> [is encoding].</param>
/// <returns>System.String.</returns>
protected abstract string GetCommandLineArguments(string outputPath, StreamState state, bool performSubtitleConversions);
protected abstract string GetCommandLineArguments(string outputPath, StreamState state, bool isEncoding);

/// <summary>
/// Gets the type of the transcoding job.
Expand Down Expand Up @@ -478,12 +478,10 @@ protected string GetAudioFilterParam(StreamState state, bool isHls)
/// </summary>
/// <param name="state">The state.</param>
/// <param name="outputVideoCodec">The output video codec.</param>
/// <param name="performTextSubtitleConversion">if set to <c>true</c> [perform text subtitle conversion].</param>
/// <param name="cancellationToken">The cancellation token.</param>
/// <returns>System.String.</returns>
protected string GetOutputSizeParam(StreamState state,
string outputVideoCodec,
bool performTextSubtitleConversion,
CancellationToken cancellationToken)
{
// http://sonnati.wordpress.com/2012/10/19/ffmpeg-the-swiss-army-knife-of-internet-streaming-part-vi/
Expand All @@ -496,7 +494,7 @@ protected string GetOutputSizeParam(StreamState state,

if (state.SubtitleStream != null && !state.SubtitleStream.IsGraphicalSubtitleStream)
{
assSubtitleParam = GetTextSubtitleParam(state, performTextSubtitleConversion, cancellationToken);
assSubtitleParam = GetTextSubtitleParam(state, cancellationToken);
copyTsParam = " -copyts";
}

Expand Down Expand Up @@ -574,103 +572,41 @@ protected string GetOutputSizeParam(StreamState state,
/// Gets the text subtitle param.
/// </summary>
/// <param name="state">The state.</param>
/// <param name="performConversion">if set to <c>true</c> [perform conversion].</param>
/// <param name="cancellationToken">The cancellation token.</param>
/// <returns>System.String.</returns>
protected string GetTextSubtitleParam(StreamState state,
bool performConversion,
CancellationToken cancellationToken)
{
var path = state.SubtitleStream.IsExternal ?
GetConvertedAssPath(state.SubtitleStream, performConversion, cancellationToken) :
GetExtractedAssPath(state, performConversion, cancellationToken);

if (string.IsNullOrEmpty(path))
{
return string.Empty;
}

var seconds = TimeSpan.FromTicks(state.Request.StartTimeTicks ?? 0).TotalSeconds;

return string.Format(",ass='{0}',setpts=PTS -{1}/TB",
path.Replace('\\', '/').Replace(":/", "\\:/"),
Math.Round(seconds).ToString(UsCulture));
}

/// <summary>
/// Gets the extracted ass path.
/// </summary>
/// <param name="state">The state.</param>
/// <param name="performConversion">if set to <c>true</c> [perform conversion].</param>
/// <param name="cancellationToken">The cancellation token.</param>
/// <returns>System.String.</returns>
private string GetExtractedAssPath(StreamState state,
bool performConversion,
CancellationToken cancellationToken)
{
var path = EncodingManager.GetSubtitleCachePath(state.MediaPath, state.SubtitleStream.Index, ".ass");

if (performConversion)
if (state.SubtitleStream.IsExternal)
{
InputType type;
var subtitlePath = state.SubtitleStream.Path;

var inputPath = MediaEncoderHelpers.GetInputArgument(state.MediaPath, state.IsRemote, state.VideoType, state.IsoType, null, state.PlayableStreamFileNames, out type);
var charsetParam = string.Empty;

try
if (!string.IsNullOrEmpty(state.SubtitleStream.Language))
{
var parentPath = Path.GetDirectoryName(path);
var charenc = MediaEncoder.GetSubtitleLanguageEncodingParam(subtitlePath, state.SubtitleStream.Language);

Directory.CreateDirectory(parentPath);

// Don't re-encode ass/ssa to ass because ffmpeg ass encoder fails if there's more than one ass rectangle. Affect Anime mostly.
// See https://lists.ffmpeg.org/pipermail/ffmpeg-cvslog/2013-April/063616.html
var isAssSubtitle = string.Equals(state.SubtitleStream.Codec, "ass", StringComparison.OrdinalIgnoreCase) || string.Equals(state.SubtitleStream.Codec, "ssa", StringComparison.OrdinalIgnoreCase);

var task = MediaEncoder.ExtractTextSubtitle(inputPath, type, state.SubtitleStream.Index, isAssSubtitle, path, cancellationToken);

Task.WaitAll(task);
}
catch
{
return null;
if (!string.IsNullOrEmpty(charenc))
{
charsetParam = ":charenc=" + charenc;
}
}
}

return path;
}

/// <summary>
/// Gets the converted ass path.
/// </summary>
/// <param name="subtitleStream">The subtitle stream.</param>
/// <param name="performConversion">if set to <c>true</c> [perform conversion].</param>
/// <param name="cancellationToken">The cancellation token.</param>
/// <returns>System.String.</returns>
private string GetConvertedAssPath(MediaStream subtitleStream,
bool performConversion,
CancellationToken cancellationToken)
{
var path = EncodingManager.GetSubtitleCachePath(subtitleStream.Path, ".ass");
// TODO: Perhaps also use original_size=1920x800

if (performConversion)
{
try
{
var parentPath = Path.GetDirectoryName(path);

Directory.CreateDirectory(parentPath);

var task = MediaEncoder.ConvertTextSubtitleToAss(subtitleStream.Path, path, subtitleStream.Language, cancellationToken);

Task.WaitAll(task);
}
catch
{
return null;
}
return string.Format(",subtitles=filename='{0}'{1},setpts=PTS -{2}/TB",
subtitlePath.Replace('\\', '/').Replace(":/", "\\:/"),
charsetParam,
Math.Round(seconds).ToString(UsCulture));
}

return path;
return string.Format(",subtitles='{0}:si={1}',setpts=PTS -{2}/TB",
state.MediaPath.Replace('\\', '/').Replace(":/", "\\:/"),
state.SubtitleStream.Index.ToString(UsCulture),
Math.Round(seconds).ToString(UsCulture));
}

/// <summary>
Expand All @@ -688,7 +624,7 @@ protected string GetInternalGraphicalSubtitleParam(StreamState state, string out
// Add resolution params, if specified
if (request.Width.HasValue || request.Height.HasValue || request.MaxHeight.HasValue || request.MaxWidth.HasValue)
{
outputSizeParam = GetOutputSizeParam(state, outputVideoCodec, false, CancellationToken.None).TrimEnd('"');
outputSizeParam = GetOutputSizeParam(state, outputVideoCodec, CancellationToken.None).TrimEnd('"');
outputSizeParam = "," + outputSizeParam.Substring(outputSizeParam.IndexOf("scale", StringComparison.OrdinalIgnoreCase));
}

Expand Down Expand Up @@ -1585,7 +1521,7 @@ protected async Task<StreamState> GetState(StreamRequest request, CancellationTo
state.OutputAudioCodec = GetAudioCodec(state.Request);

state.OutputAudioChannels = GetNumAudioChannelsParam(state.Request, state.AudioStream, state.OutputAudioCodec);

if (videoRequest != null)
{
state.OutputVideoCodec = GetVideoCodec(videoRequest);
Expand Down
11 changes: 5 additions & 6 deletions MediaBrowser.Api/Playback/Hls/BaseHlsService.cs
Original file line number Diff line number Diff line change
Expand Up @@ -39,9 +39,8 @@ protected BaseHlsService(IServerConfigurationManager serverConfig, IUserManager
/// Gets the video arguments.
/// </summary>
/// <param name="state">The state.</param>
/// <param name="performSubtitleConversion">if set to <c>true</c> [perform subtitle conversion].</param>
/// <returns>System.String.</returns>
protected abstract string GetVideoArguments(StreamState state, bool performSubtitleConversion);
protected abstract string GetVideoArguments(StreamState state);

/// <summary>
/// Gets the segment file extension.
Expand Down Expand Up @@ -272,9 +271,9 @@ private static int CountStringOccurrences(string text, string pattern)
/// </summary>
/// <param name="outputPath">The output path.</param>
/// <param name="state">The state.</param>
/// <param name="performSubtitleConversions">if set to <c>true</c> [perform subtitle conversions].</param>
/// <param name="isEncoding">if set to <c>true</c> [is encoding].</param>
/// <returns>System.String.</returns>
protected override string GetCommandLineArguments(string outputPath, StreamState state, bool performSubtitleConversions)
protected override string GetCommandLineArguments(string outputPath, StreamState state, bool isEncoding)
{
var hlsVideoRequest = state.VideoRequest as GetHlsVideoStream;

Expand All @@ -289,15 +288,15 @@ protected override string GetCommandLineArguments(string outputPath, StreamState
var inputModifier = GetInputModifier(state);

// If performSubtitleConversions is true we're actually starting ffmpeg
var startNumberParam = performSubtitleConversions ? GetStartNumber(state).ToString(UsCulture) : "0";
var startNumberParam = isEncoding ? GetStartNumber(state).ToString(UsCulture) : "0";

var args = string.Format("{0} {1} -i {2} -map_metadata -1 -threads {3} {4} {5} -sc_threshold 0 {6} -hls_time {7} -start_number {8} -hls_list_size {9} -y \"{10}\"",
itsOffset,
inputModifier,
GetInputArgument(state),
threads,
GetMapArgs(state),
GetVideoArguments(state, performSubtitleConversions),
GetVideoArguments(state),
GetAudioArguments(state),
state.SegmentLength.ToString(UsCulture),
startNumberParam,
Expand Down
4 changes: 2 additions & 2 deletions MediaBrowser.Api/Playback/Hls/DynamicHlsService.cs
Original file line number Diff line number Diff line change
Expand Up @@ -264,7 +264,7 @@ protected override string GetAudioArguments(StreamState state)
return args;
}

protected override string GetVideoArguments(StreamState state, bool performSubtitleConversion)
protected override string GetVideoArguments(StreamState state)
{
var codec = state.OutputVideoCodec;

Expand All @@ -285,7 +285,7 @@ protected override string GetVideoArguments(StreamState state, bool performSubti
{
if (state.VideoRequest.Width.HasValue || state.VideoRequest.Height.HasValue || state.VideoRequest.MaxHeight.HasValue || state.VideoRequest.MaxWidth.HasValue)
{
args += GetOutputSizeParam(state, codec, performSubtitleConversion, CancellationToken.None);
args += GetOutputSizeParam(state, codec, CancellationToken.None);
}
}

Expand Down
6 changes: 2 additions & 4 deletions MediaBrowser.Api/Playback/Hls/VideoHlsService.cs
Original file line number Diff line number Diff line change
Expand Up @@ -155,10 +155,8 @@ protected override string GetAudioArguments(StreamState state)
/// Gets the video arguments.
/// </summary>
/// <param name="state">The state.</param>
/// <param name="performSubtitleConversion">if set to <c>true</c> [perform subtitle conversion].</param>
/// <returns>System.String.</returns>
protected override string GetVideoArguments(StreamState state,
bool performSubtitleConversion)
protected override string GetVideoArguments(StreamState state)
{
var codec = state.OutputVideoCodec;

Expand All @@ -181,7 +179,7 @@ protected override string GetVideoArguments(StreamState state,
{
if (state.VideoRequest.Width.HasValue || state.VideoRequest.Height.HasValue || state.VideoRequest.MaxHeight.HasValue || state.VideoRequest.MaxWidth.HasValue)
{
args += GetOutputSizeParam(state, codec, performSubtitleConversion, CancellationToken.None);
args += GetOutputSizeParam(state, codec, CancellationToken.None);
}
}

Expand Down
4 changes: 2 additions & 2 deletions MediaBrowser.Api/Playback/Progressive/AudioService.cs
Original file line number Diff line number Diff line change
Expand Up @@ -73,10 +73,10 @@ public object Head(GetAudioStream request)
/// </summary>
/// <param name="outputPath">The output path.</param>
/// <param name="state">The state.</param>
/// <param name="performSubtitleConversions">if set to <c>true</c> [perform subtitle conversions].</param>
/// <param name="isEncoding">if set to <c>true</c> [is encoding].</param>
/// <returns>System.String.</returns>
/// <exception cref="System.InvalidOperationException">Only aac and mp3 audio codecs are supported.</exception>
protected override string GetCommandLineArguments(string outputPath, StreamState state, bool performSubtitleConversions)
protected override string GetCommandLineArguments(string outputPath, StreamState state, bool isEncoding)
{
var audioTranscodeParams = new List<string>();

Expand Down
13 changes: 6 additions & 7 deletions MediaBrowser.Api/Playback/Progressive/VideoService.cs
Original file line number Diff line number Diff line change
@@ -1,4 +1,3 @@
using System.Threading;
using MediaBrowser.Common.IO;
using MediaBrowser.Common.Net;
using MediaBrowser.Controller.Channels;
Expand All @@ -14,6 +13,7 @@
using ServiceStack;
using System;
using System.IO;
using System.Threading;

namespace MediaBrowser.Api.Playback.Progressive
{
Expand Down Expand Up @@ -90,9 +90,9 @@ public object Head(GetVideoStream request)
/// </summary>
/// <param name="outputPath">The output path.</param>
/// <param name="state">The state.</param>
/// <param name="performSubtitleConversions">if set to <c>true</c> [perform subtitle conversions].</param>
/// <param name="isEncoding">if set to <c>true</c> [is encoding].</param>
/// <returns>System.String.</returns>
protected override string GetCommandLineArguments(string outputPath, StreamState state, bool performSubtitleConversions)
protected override string GetCommandLineArguments(string outputPath, StreamState state, bool isEncoding)
{
// Get the output codec name
var videoCodec = state.OutputVideoCodec;
Expand All @@ -114,7 +114,7 @@ protected override string GetCommandLineArguments(string outputPath, StreamState
GetInputArgument(state),
keyFrame,
GetMapArgs(state),
GetVideoArguments(state, videoCodec, performSubtitleConversions),
GetVideoArguments(state, videoCodec),
threads,
GetAudioArguments(state),
format,
Expand All @@ -127,9 +127,8 @@ protected override string GetCommandLineArguments(string outputPath, StreamState
/// </summary>
/// <param name="state">The state.</param>
/// <param name="codec">The video codec.</param>
/// <param name="performSubtitleConversion">if set to <c>true</c> [perform subtitle conversion].</param>
/// <returns>System.String.</returns>
private string GetVideoArguments(StreamState state, string codec, bool performSubtitleConversion)
private string GetVideoArguments(StreamState state, string codec)
{
var args = "-vcodec " + codec;

Expand Down Expand Up @@ -157,7 +156,7 @@ private string GetVideoArguments(StreamState state, string codec, bool performSu
{
if (request.Width.HasValue || request.Height.HasValue || request.MaxHeight.HasValue || request.MaxWidth.HasValue)
{
args += GetOutputSizeParam(state, codec, performSubtitleConversion, CancellationToken.None);
args += GetOutputSizeParam(state, codec, CancellationToken.None);
}
}

Expand Down
5 changes: 5 additions & 0 deletions MediaBrowser.Controller/Channels/ChannelSearchInfo.cs
Original file line number Diff line number Diff line change
Expand Up @@ -6,4 +6,9 @@ public class ChannelSearchInfo

public string UserId { get; set; }
}

public class ChannelLatestMediaSearch
{
public string UserId { get; set; }
}
}
11 changes: 11 additions & 0 deletions MediaBrowser.Controller/Channels/ISearchableChannel.cs
Original file line number Diff line number Diff line change
Expand Up @@ -14,4 +14,15 @@ public interface ISearchableChannel
/// <returns>Task{IEnumerable{ChannelItemInfo}}.</returns>
Task<IEnumerable<ChannelItemInfo>> Search(ChannelSearchInfo searchInfo, CancellationToken cancellationToken);
}

public interface ISupportsLatestMedia
{
/// <summary>
/// Gets the latest media.
/// </summary>
/// <param name="request">The request.</param>
/// <param name="cancellationToken">The cancellation token.</param>
/// <returns>Task{IEnumerable{ChannelItemInfo}}.</returns>
Task<IEnumerable<ChannelItemInfo>> GetLatestMedia(ChannelLatestMediaSearch request, CancellationToken cancellationToken);
}
}
17 changes: 17 additions & 0 deletions MediaBrowser.Controller/Chapters/IChapterManager.cs
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@
using System.Collections.Generic;
using System.Threading;
using System.Threading.Tasks;
using MediaBrowser.Model.Entities;

namespace MediaBrowser.Controller.Chapters
{
Expand All @@ -17,6 +18,22 @@ public interface IChapterManager
/// <param name="chapterProviders">The chapter providers.</param>
void AddParts(IEnumerable<IChapterProvider> chapterProviders);

/// <summary>
/// Gets the chapters.
/// </summary>
/// <param name="itemId">The item identifier.</param>
/// <returns>List{ChapterInfo}.</returns>
IEnumerable<ChapterInfo> GetChapters(string itemId);

/// <summary>
/// Saves the chapters.
/// </summary>
/// <param name="itemId">The item identifier.</param>
/// <param name="chapters">The chapters.</param>
/// <param name="cancellationToken">The cancellation token.</param>
/// <returns>Task.</returns>
Task SaveChapters(string itemId, IEnumerable<ChapterInfo> chapters, CancellationToken cancellationToken);

/// <summary>
/// Searches the specified video.
/// </summary>
Expand Down
6 changes: 6 additions & 0 deletions MediaBrowser.Controller/LiveTv/ILiveTvManager.cs
Original file line number Diff line number Diff line change
Expand Up @@ -274,5 +274,11 @@ Task<QueryResult<ProgramInfoDto>> GetRecommendedPrograms(RecommendedProgramQuery
/// <param name="cancellationToken">The cancellation token.</param>
/// <returns>BaseItemDto.</returns>
Task<BaseItemDto> GetLiveTvFolder(string userId, CancellationToken cancellationToken);

/// <summary>
/// Gets the enabled users.
/// </summary>
/// <returns>IEnumerable{User}.</returns>
IEnumerable<User> GetEnabledUsers();
}
}
Loading

0 comments on commit 67ae275

Please sign in to comment.