124 lines
3.6 KiB
C#
124 lines
3.6 KiB
C#
using System;
|
|
using System.IO;
|
|
using System.Linq;
|
|
using System.Threading.Tasks;
|
|
using AAXClean;
|
|
using AAXClean.Codecs;
|
|
using DataLayer;
|
|
using Dinah.Core.ErrorHandling;
|
|
using Dinah.Core.Net.Http;
|
|
using FileManager;
|
|
using LibationFileManager;
|
|
|
|
namespace FileLiberator
|
|
{
|
|
public class ConvertToMp3 : AudioDecodable
|
|
{
|
|
public override string Name => "Convert to Mp3";
|
|
private Mp4File m4bBook;
|
|
|
|
private long fileSize;
|
|
private static string Mp3FileName(string m4bPath) => Path.ChangeExtension(m4bPath ?? "", ".mp3");
|
|
|
|
public override Task CancelAsync() => m4bBook?.CancelAsync() ?? Task.CompletedTask;
|
|
|
|
public static bool ValidateMp3(LibraryBook libraryBook)
|
|
{
|
|
var paths = AudibleFileStorage.Audio.GetPaths(libraryBook.Book.AudibleProductId);
|
|
return paths.Any(path => path?.ToString()?.ToLower()?.EndsWith(".m4b") == true && !File.Exists(Mp3FileName(path)));
|
|
}
|
|
|
|
public override bool Validate(LibraryBook libraryBook) => ValidateMp3(libraryBook);
|
|
|
|
public override async Task<StatusHandler> ProcessAsync(LibraryBook libraryBook)
|
|
{
|
|
OnBegin(libraryBook);
|
|
|
|
try
|
|
{
|
|
var m4bPaths = AudibleFileStorage.Audio.GetPaths(libraryBook.Book.AudibleProductId);
|
|
|
|
foreach (var m4bPath in m4bPaths)
|
|
{
|
|
var proposedMp3Path = Mp3FileName(m4bPath);
|
|
if (File.Exists(proposedMp3Path) || !File.Exists(m4bPath)) continue;
|
|
|
|
m4bBook = await Task.Run(() => new Mp4File(m4bPath, FileAccess.Read));
|
|
m4bBook.ConversionProgressUpdate += M4bBook_ConversionProgressUpdate;
|
|
|
|
fileSize = m4bBook.InputStream.Length;
|
|
|
|
OnTitleDiscovered(m4bBook.AppleTags.Title);
|
|
OnAuthorsDiscovered(m4bBook.AppleTags.FirstAuthor);
|
|
OnNarratorsDiscovered(m4bBook.AppleTags.Narrator);
|
|
OnCoverImageDiscovered(m4bBook.AppleTags.Cover);
|
|
|
|
var config = Configuration.Instance;
|
|
var lameConfig = GetLameOptions(config);
|
|
|
|
//Finishing configuring lame encoder.
|
|
AaxDecrypter.MpegUtil.ConfigureLameOptions(
|
|
m4bBook,
|
|
lameConfig,
|
|
config.LameDownsampleMono,
|
|
config.LameMatchSourceBR);
|
|
|
|
using var mp3File = File.OpenWrite(Path.GetTempFileName());
|
|
try
|
|
{
|
|
var result = await m4bBook.ConvertToMp3Async(mp3File, lameConfig);
|
|
|
|
var realMp3Path = FileUtility.SaferMoveToValidPath(mp3File.Name, proposedMp3Path, Configuration.Instance.ReplacementCharacters);
|
|
OnFileCreated(libraryBook, realMp3Path);
|
|
|
|
if (result == ConversionResult.Failed)
|
|
{
|
|
FileUtility.SaferDelete(mp3File.Name);
|
|
}
|
|
else if (result == ConversionResult.Cancelled)
|
|
{
|
|
FileUtility.SaferDelete(mp3File.Name);
|
|
return new StatusHandler { "Cancelled" };
|
|
}
|
|
}
|
|
catch (Exception ex)
|
|
{
|
|
Serilog.Log.Error(ex, "AAXClean error");
|
|
return new StatusHandler { "Conversion failed" };
|
|
}
|
|
finally
|
|
{
|
|
m4bBook.InputStream.Close();
|
|
mp3File.Close();
|
|
}
|
|
}
|
|
}
|
|
finally
|
|
{
|
|
OnCompleted(libraryBook);
|
|
}
|
|
return new StatusHandler();
|
|
}
|
|
|
|
private void M4bBook_ConversionProgressUpdate(object sender, ConversionProgressEventArgs e)
|
|
{
|
|
var duration = m4bBook.Duration;
|
|
var remainingSecsToProcess = (duration - e.ProcessPosition).TotalSeconds;
|
|
var estTimeRemaining = remainingSecsToProcess / e.ProcessSpeed;
|
|
|
|
if (double.IsNormal(estTimeRemaining))
|
|
OnStreamingTimeRemaining(TimeSpan.FromSeconds(estTimeRemaining));
|
|
|
|
double progressPercent = 100 * e.ProcessPosition.TotalSeconds / duration.TotalSeconds;
|
|
|
|
OnStreamingProgressChanged(
|
|
new DownloadProgress
|
|
{
|
|
ProgressPercentage = progressPercent,
|
|
BytesReceived = (long)(fileSize * progressPercent),
|
|
TotalBytesToReceive = fileSize
|
|
});
|
|
}
|
|
}
|
|
}
|