mirror of
https://github.com/rmcrackan/Libation.git
synced 2026-02-18 00:17:43 +01:00
Add option to adjust minimum file duration
when splitting audiobooks into multiple files by chapter
This commit is contained in:
@@ -40,58 +40,14 @@ namespace AaxDecrypter
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
https://github.com/rmcrackan/Libation/pull/127#issuecomment-939088489
|
||||
|
||||
If the chapter truly is empty, that is, 0 audio frames in length, then yes it is ignored.
|
||||
If the chapter is shorter than 3 seconds long but still has some audio frames, those frames are combined with the following chapter and not split into a new file.
|
||||
|
||||
I also implemented file naming by chapter title. When 2 or more consecutive chapters are combined, the first of the combined chapter's title is used in the file name. For example, given an audiobook with the following chapters:
|
||||
|
||||
00:00:00 - 00:00:02 | Part 1
|
||||
00:00:02 - 00:35:00 | Chapter 1
|
||||
00:35:02 - 01:02:00 | Chapter 2
|
||||
01:02:00 - 01:02:02 | Part 2
|
||||
01:02:02 - 01:41:00 | Chapter 3
|
||||
01:41:00 - 02:05:00 | Chapter 4
|
||||
|
||||
The book will be split into the following files:
|
||||
|
||||
00:00:00 - 00:35:00 | Book - 01 - Part 1.m4b
|
||||
00:35:00 - 01:02:00 | Book - 02 - Chapter 2.m4b
|
||||
01:02:00 - 01:41:00 | Book - 03 - Part 2.m4b
|
||||
01:41:00 - 02:05:00 | Book - 04 - Chapter 4.m4b
|
||||
|
||||
That naming may not be desirable for everyone, but it's an easy change to instead use the last of the combined chapter's title in the file name.
|
||||
*/
|
||||
protected async override Task<bool> Step_DownloadAndDecryptAudiobookAsync()
|
||||
{
|
||||
if (AaxFile is null) return false;
|
||||
var chapters = DownloadOptions.ChapterInfo.Chapters;
|
||||
|
||||
// Ensure split files are at least minChapterLength in duration.
|
||||
var splitChapters = new ChapterInfo(DownloadOptions.ChapterInfo.StartOffset);
|
||||
|
||||
var runningTotal = TimeSpan.Zero;
|
||||
string title = "";
|
||||
|
||||
for (int i = 0; i < chapters.Count; i++)
|
||||
{
|
||||
if (runningTotal == TimeSpan.Zero)
|
||||
title = chapters[i].Title;
|
||||
|
||||
runningTotal += chapters[i].Duration;
|
||||
|
||||
if (runningTotal >= minChapterLength)
|
||||
{
|
||||
splitChapters.AddChapter(title, runningTotal);
|
||||
runningTotal = TimeSpan.Zero;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
try
|
||||
{
|
||||
await (AaxConversion = decryptMultiAsync(AaxFile, splitChapters));
|
||||
await (AaxConversion = decryptMultiAsync(AaxFile, DownloadOptions.ChapterInfo));
|
||||
|
||||
if (AaxConversion.IsCompletedSuccessfully)
|
||||
await moveMoovToBeginning(AaxFile, workingFileStream?.Name);
|
||||
|
||||
@@ -170,17 +170,6 @@ public partial class DownloadOptions
|
||||
/// </summary>
|
||||
public static DownloadOptions BuildDownloadOptions(LibraryBook libraryBook, Configuration config, LicenseInfo licInfo)
|
||||
{
|
||||
long chapterStartMs
|
||||
= config.StripAudibleBrandAudio
|
||||
? licInfo.ContentMetadata.ChapterInfo.BrandIntroDurationMs
|
||||
: 0;
|
||||
|
||||
var dlOptions = new DownloadOptions(config, libraryBook, licInfo)
|
||||
{
|
||||
ChapterInfo = new AAXClean.ChapterInfo(TimeSpan.FromMilliseconds(chapterStartMs)),
|
||||
RuntimeLength = TimeSpan.FromMilliseconds(licInfo.ContentMetadata.ChapterInfo.RuntimeLengthMs),
|
||||
};
|
||||
|
||||
var titleConcat = config.CombineNestedChapterTitles ? ": " : null;
|
||||
var chapters
|
||||
= flattenChapters(licInfo.ContentMetadata.ChapterInfo.Chapters, titleConcat)
|
||||
@@ -190,18 +179,22 @@ public partial class DownloadOptions
|
||||
if (config.MergeOpeningAndEndCredits)
|
||||
combineCredits(chapters);
|
||||
|
||||
if (config.StripAudibleBrandAudio)
|
||||
stripBranding(chapters, licInfo.ContentMetadata.ChapterInfo.BrandIntroDurationMs, licInfo.ContentMetadata.ChapterInfo.BrandOutroDurationMs);
|
||||
|
||||
if (config.SplitFilesByChapter)
|
||||
combineShortChapters(chapters, config.MinimumFileDuration * 1000);
|
||||
|
||||
var dlOptions = new DownloadOptions(config, libraryBook, licInfo)
|
||||
{
|
||||
ChapterInfo = new AAXClean.ChapterInfo(TimeSpan.FromMilliseconds(chapters[0].StartOffsetMs)),
|
||||
RuntimeLength = TimeSpan.FromMilliseconds(licInfo.ContentMetadata.ChapterInfo.RuntimeLengthMs),
|
||||
};
|
||||
|
||||
//Build AAXClean.ChapterInfo
|
||||
for (int i = 0; i < chapters.Count; i++)
|
||||
{
|
||||
var chapter = chapters[i];
|
||||
long chapLenMs = chapter.LengthMs;
|
||||
|
||||
if (i == 0)
|
||||
chapLenMs -= chapterStartMs;
|
||||
|
||||
if (config.StripAudibleBrandAudio && i == chapters.Count - 1)
|
||||
chapLenMs -= licInfo.ContentMetadata.ChapterInfo.BrandOutroDurationMs;
|
||||
|
||||
dlOptions.ChapterInfo.AddChapter(chapter.Title, TimeSpan.FromMilliseconds(chapLenMs));
|
||||
dlOptions.ChapterInfo.AddChapter(chapters[i].Title, TimeSpan.FromMilliseconds(chapters[i].LengthMs));
|
||||
}
|
||||
|
||||
return dlOptions;
|
||||
@@ -349,6 +342,50 @@ public partial class DownloadOptions
|
||||
return chaps;
|
||||
}
|
||||
|
||||
/*
|
||||
https://github.com/rmcrackan/Libation/pull/127#issuecomment-939088489
|
||||
|
||||
If the chapter truly is empty, that is, 0 audio frames in length, then yes it is ignored.
|
||||
If the chapter is shorter than minChapterLength but still has some audio frames, those
|
||||
frames are combined with the following chapter and not split into a new file.
|
||||
|
||||
When 2 or more consecutive chapters are combined, chapter titles are concatenated
|
||||
with a apace in between. For example, given an audiobook with the following chapters:
|
||||
|
||||
00:00:00 - 00:00:02 | Part 1
|
||||
00:00:02 - 00:35:00 | Chapter 1
|
||||
00:35:02 - 01:02:00 | Chapter 2
|
||||
01:02:00 - 01:02:02 | Part 2
|
||||
01:02:02 - 01:41:00 | Chapter 3
|
||||
01:41:00 - 02:05:00 | Chapter 4
|
||||
|
||||
The book will be split into the following files:
|
||||
|
||||
00:00:00 - 00:35:00 | Book - 01 - Part 1 Chapter 1.m4b
|
||||
00:35:00 - 01:02:00 | Book - 02 - Chapter 2.m4b
|
||||
01:02:00 - 01:41:00 | Book - 03 - Part 2.m4b
|
||||
01:41:00 - 02:05:00 | Book - 04 - Chapter 4.m4b
|
||||
*/
|
||||
public static void combineShortChapters(List<Chapter> chapters, long minChapterLengthMs)
|
||||
{
|
||||
for (int i = 0; i < chapters.Count; i++)
|
||||
{
|
||||
while (chapters[i].LengthMs < minChapterLengthMs && chapters.Count > i + 1)
|
||||
{
|
||||
chapters[i].Title += " " + chapters[i + 1].Title;
|
||||
chapters[i].LengthMs += chapters[i + 1].LengthMs;
|
||||
chapters.RemoveAt(i + 1);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public static void stripBranding(List<Chapter> chapters, long introMs, long outroMs)
|
||||
{
|
||||
chapters[0].LengthMs -= introMs;
|
||||
chapters[0].StartOffsetMs += introMs;
|
||||
chapters[^1].LengthMs -= outroMs;
|
||||
}
|
||||
|
||||
public static void combineCredits(IList<Chapter> chapters)
|
||||
{
|
||||
if (chapters.Count > 1 && chapters[0].Title == "Opening Credits")
|
||||
|
||||
@@ -101,6 +101,29 @@
|
||||
<Setter Property="BorderThickness" Value="2" />
|
||||
</Style>
|
||||
</Style>
|
||||
|
||||
<Style Selector="NumericUpDown.SmallNumericUpDown">
|
||||
<Setter Property="Height" Value="{DynamicResource TextControlThemeMinHeight}" />
|
||||
<Setter Property="HorizontalContentAlignment" Value="Center" />
|
||||
<Style Selector="^ /template/ ButtonSpinner#PART_Spinner">
|
||||
<Style Selector="^ RepeatButton#PART_IncreaseButton">
|
||||
<Setter Property="MinWidth" Value="24" />
|
||||
<Style Selector="^ > PathIcon">
|
||||
<Setter Property="Data">
|
||||
M0,0 l8,-10 l8,10 Z
|
||||
</Setter>
|
||||
</Style>
|
||||
</Style>
|
||||
<Style Selector="^ RepeatButton#PART_DecreaseButton">
|
||||
<Setter Property="MinWidth" Value="24" />
|
||||
<Style Selector="^ > PathIcon">
|
||||
<Setter Property="Data">
|
||||
M0,0 l8,10 l8,-10 Z
|
||||
</Setter>
|
||||
</Style>
|
||||
</Style>
|
||||
</Style>
|
||||
</Style>
|
||||
</Application.Styles>
|
||||
|
||||
<NativeMenu.Menu>
|
||||
|
||||
@@ -6,6 +6,7 @@
|
||||
xmlns:controls="clr-namespace:LibationAvalonia.Controls"
|
||||
xmlns:vm="clr-namespace:LibationAvalonia.ViewModels.Settings"
|
||||
x:DataType="vm:AudioSettingsVM"
|
||||
x:CompileBindings="True"
|
||||
x:Class="LibationAvalonia.Controls.Settings.Audio">
|
||||
|
||||
<Grid
|
||||
@@ -38,43 +39,43 @@
|
||||
<Grid ColumnDefinitions="*,Auto">
|
||||
<TextBlock
|
||||
VerticalAlignment="Center"
|
||||
Text="{CompiledBinding FileDownloadQualityText}" />
|
||||
Text="{Binding FileDownloadQualityText}" />
|
||||
|
||||
<controls:WheelComboBox
|
||||
Margin="5,0,0,0"
|
||||
Grid.Column="1"
|
||||
ItemsSource="{CompiledBinding DownloadQualities}"
|
||||
SelectedItem="{CompiledBinding FileDownloadQuality}"/>
|
||||
ItemsSource="{Binding DownloadQualities}"
|
||||
SelectedItem="{Binding FileDownloadQuality}"/>
|
||||
</Grid>
|
||||
|
||||
<Grid ColumnDefinitions="*,Auto">
|
||||
<CheckBox
|
||||
ToolTip.Tip="{CompiledBinding UseWidevineTip}"
|
||||
ToolTip.Tip="{Binding UseWidevineTip}"
|
||||
IsCheckedChanged="UseWidevine_IsCheckedChanged"
|
||||
IsChecked="{CompiledBinding UseWidevine, Mode=TwoWay}">
|
||||
<TextBlock Text="{CompiledBinding UseWidevineText}" />
|
||||
IsChecked="{Binding UseWidevine, Mode=TwoWay}">
|
||||
<TextBlock Text="{Binding UseWidevineText}" />
|
||||
</CheckBox>
|
||||
<CheckBox
|
||||
Grid.Column="1"
|
||||
ToolTip.Tip="{CompiledBinding Request_xHE_AACTip}"
|
||||
IsEnabled="{CompiledBinding UseWidevine}"
|
||||
IsChecked="{CompiledBinding Request_xHE_AAC, Mode=TwoWay}">
|
||||
<TextBlock Text="{CompiledBinding Request_xHE_AACText}" />
|
||||
ToolTip.Tip="{Binding Request_xHE_AACTip}"
|
||||
IsEnabled="{Binding UseWidevine}"
|
||||
IsChecked="{Binding Request_xHE_AAC, Mode=TwoWay}">
|
||||
<TextBlock Text="{Binding Request_xHE_AACText}" />
|
||||
</CheckBox>
|
||||
</Grid>
|
||||
|
||||
<Grid ColumnDefinitions="*,Auto">
|
||||
<CheckBox
|
||||
ToolTip.Tip="{CompiledBinding RequestSpatialTip}"
|
||||
IsEnabled="{CompiledBinding UseWidevine}"
|
||||
IsChecked="{CompiledBinding RequestSpatial, Mode=TwoWay}">
|
||||
<TextBlock Text="{CompiledBinding RequestSpatialText}" />
|
||||
ToolTip.Tip="{Binding RequestSpatialTip}"
|
||||
IsEnabled="{Binding UseWidevine}"
|
||||
IsChecked="{Binding RequestSpatial, Mode=TwoWay}">
|
||||
<TextBlock Text="{Binding RequestSpatialText}" />
|
||||
</CheckBox>
|
||||
<Grid
|
||||
Grid.Column="1"
|
||||
ColumnDefinitions="Auto,Auto"
|
||||
VerticalAlignment="Top"
|
||||
ToolTip.Tip="{CompiledBinding SpatialAudioCodecTip}">
|
||||
ToolTip.Tip="{Binding SpatialAudioCodecTip}">
|
||||
<Grid.IsEnabled>
|
||||
<MultiBinding Converter="{x:Static BoolConverters.And}">
|
||||
<MultiBinding.Bindings>
|
||||
@@ -92,78 +93,100 @@
|
||||
Margin="5,0,0,0"
|
||||
Grid.Column="1"
|
||||
VerticalAlignment="Center"
|
||||
ItemsSource="{CompiledBinding SpatialAudioCodecs}"
|
||||
SelectedItem="{CompiledBinding SpatialAudioCodec}"/>
|
||||
ItemsSource="{Binding SpatialAudioCodecs}"
|
||||
SelectedItem="{Binding SpatialAudioCodec}"/>
|
||||
</Grid>
|
||||
|
||||
</Grid>
|
||||
|
||||
<CheckBox IsChecked="{CompiledBinding CreateCueSheet, Mode=TwoWay}">
|
||||
<TextBlock Text="{CompiledBinding CreateCueSheetText}" />
|
||||
<CheckBox IsChecked="{Binding CreateCueSheet, Mode=TwoWay}">
|
||||
<TextBlock Text="{Binding CreateCueSheetText}" />
|
||||
</CheckBox>
|
||||
|
||||
<CheckBox IsChecked="{CompiledBinding DownloadCoverArt, Mode=TwoWay}">
|
||||
<TextBlock Text="{CompiledBinding DownloadCoverArtText}" />
|
||||
<CheckBox IsChecked="{Binding DownloadCoverArt, Mode=TwoWay}">
|
||||
<TextBlock Text="{Binding DownloadCoverArtText}" />
|
||||
</CheckBox>
|
||||
|
||||
<Grid ColumnDefinitions="*,Auto">
|
||||
<CheckBox IsChecked="{CompiledBinding DownloadClipsBookmarks, Mode=TwoWay}">
|
||||
<CheckBox IsChecked="{Binding DownloadClipsBookmarks, Mode=TwoWay}">
|
||||
<TextBlock Text="Download Clips, Notes and Bookmarks as" />
|
||||
</CheckBox>
|
||||
|
||||
<controls:WheelComboBox
|
||||
Margin="5,0,0,0"
|
||||
Grid.Column="1"
|
||||
IsEnabled="{CompiledBinding DownloadClipsBookmarks}"
|
||||
ItemsSource="{CompiledBinding ClipBookmarkFormats}"
|
||||
SelectedItem="{CompiledBinding ClipBookmarkFormat}"/>
|
||||
IsEnabled="{Binding DownloadClipsBookmarks}"
|
||||
ItemsSource="{Binding ClipBookmarkFormats}"
|
||||
SelectedItem="{Binding ClipBookmarkFormat}"/>
|
||||
</Grid>
|
||||
|
||||
<CheckBox
|
||||
IsChecked="{CompiledBinding RetainAaxFile, Mode=TwoWay}"
|
||||
ToolTip.Tip="{CompiledBinding RetainAaxFileTip}">
|
||||
<TextBlock Text="{CompiledBinding RetainAaxFileText}" />
|
||||
IsChecked="{Binding RetainAaxFile, Mode=TwoWay}"
|
||||
ToolTip.Tip="{Binding RetainAaxFileTip}">
|
||||
<TextBlock Text="{Binding RetainAaxFileText}" />
|
||||
</CheckBox>
|
||||
|
||||
<CheckBox
|
||||
IsChecked="{CompiledBinding MergeOpeningAndEndCredits, Mode=TwoWay}"
|
||||
ToolTip.Tip="{CompiledBinding MergeOpeningAndEndCreditsTip}">
|
||||
<TextBlock Text="{CompiledBinding MergeOpeningEndCreditsText}" />
|
||||
IsChecked="{Binding MergeOpeningAndEndCredits, Mode=TwoWay}"
|
||||
ToolTip.Tip="{Binding MergeOpeningAndEndCreditsTip}">
|
||||
<TextBlock Text="{Binding MergeOpeningEndCreditsText}" />
|
||||
</CheckBox>
|
||||
|
||||
<CheckBox
|
||||
ToolTip.Tip="{CompiledBinding CombineNestedChapterTitlesTip}"
|
||||
IsChecked="{CompiledBinding CombineNestedChapterTitles, Mode=TwoWay}">
|
||||
<TextBlock Text="{CompiledBinding CombineNestedChapterTitlesText}" />
|
||||
ToolTip.Tip="{Binding CombineNestedChapterTitlesTip}"
|
||||
IsChecked="{Binding CombineNestedChapterTitles, Mode=TwoWay}">
|
||||
<TextBlock Text="{Binding CombineNestedChapterTitlesText}" />
|
||||
</CheckBox>
|
||||
|
||||
<CheckBox
|
||||
ToolTip.Tip="{CompiledBinding AllowLibationFixupTip}"
|
||||
IsChecked="{CompiledBinding AllowLibationFixup, Mode=TwoWay}">
|
||||
<TextBlock Text="{CompiledBinding AllowLibationFixupText}" />
|
||||
ToolTip.Tip="{Binding AllowLibationFixupTip}"
|
||||
IsChecked="{Binding AllowLibationFixup, Mode=TwoWay}">
|
||||
<TextBlock Text="{Binding AllowLibationFixupText}" />
|
||||
</CheckBox>
|
||||
|
||||
<controls:GroupBox
|
||||
Grid.Row="1"
|
||||
Label="Audiobook Fix-ups"
|
||||
IsEnabled="{CompiledBinding AllowLibationFixup}">
|
||||
IsEnabled="{Binding AllowLibationFixup}">
|
||||
|
||||
<StackPanel Orientation="Vertical">
|
||||
|
||||
<CheckBox IsChecked="{CompiledBinding SplitFilesByChapter, Mode=TwoWay}">
|
||||
<TextBlock Text="{CompiledBinding SplitFilesByChapterText}" />
|
||||
<Grid
|
||||
Margin="0,0,0,5"
|
||||
Grid.ColumnDefinitions="Auto,Auto"
|
||||
Grid.RowDefinitions="Auto,Auto">
|
||||
|
||||
<CheckBox Margin="0" Grid.ColumnSpan="2" IsChecked="{Binding SplitFilesByChapter, Mode=TwoWay}">
|
||||
<TextBlock Grid.ColumnSpan="2" Text="{Binding SplitFilesByChapterText}" />
|
||||
</CheckBox>
|
||||
|
||||
<TextBlock Grid.Row="1" Margin="15,0" VerticalAlignment="Center" ToolTip.Tip="{Binding MinimumFileDurationTip}" Text="{Binding MinimumFileDurationText}" />
|
||||
|
||||
<NumericUpDown
|
||||
Classes="SmallNumericUpDown"
|
||||
Grid.Column="1"
|
||||
Grid.Row="1"
|
||||
ToolTip.Tip="{Binding MinimumFileDurationTip}"
|
||||
MinWidth="100"
|
||||
Minimum="0"
|
||||
Maximum="120"
|
||||
Increment="1"
|
||||
FormatString="N0"
|
||||
ParsingNumberStyle="Integer"
|
||||
IsEnabled="{Binding SplitFilesByChapter}"
|
||||
Value="{Binding MinimumFileDuration, Mode=TwoWay}"/>
|
||||
</Grid>
|
||||
|
||||
<CheckBox
|
||||
IsChecked="{Binding StripAudibleBrandAudio, Mode=TwoWay}"
|
||||
ToolTip.Tip="{Binding StripAudibleBrandAudioTip}">
|
||||
<TextBlock Text="{Binding StripAudibleBrandingText}" />
|
||||
</CheckBox>
|
||||
|
||||
<CheckBox
|
||||
IsChecked="{CompiledBinding StripAudibleBrandAudio, Mode=TwoWay}"
|
||||
ToolTip.Tip="{CompiledBinding StripAudibleBrandAudioTip}">
|
||||
<TextBlock Text="{CompiledBinding StripAudibleBrandingText}" />
|
||||
</CheckBox>
|
||||
|
||||
<CheckBox
|
||||
IsChecked="{CompiledBinding StripUnabridged, Mode=TwoWay}"
|
||||
ToolTip.Tip="{CompiledBinding StripUnabridgedTip}">
|
||||
<TextBlock Text="{CompiledBinding StripUnabridgedText}" />
|
||||
IsChecked="{Binding StripUnabridged, Mode=TwoWay}"
|
||||
ToolTip.Tip="{Binding StripUnabridgedTip}">
|
||||
<TextBlock Text="{Binding StripUnabridgedText}" />
|
||||
</CheckBox>
|
||||
</StackPanel>
|
||||
</controls:GroupBox>
|
||||
@@ -178,24 +201,24 @@
|
||||
Margin="10,0,0,0">
|
||||
|
||||
<RadioButton
|
||||
IsChecked="{CompiledBinding !DecryptToLossy, Mode=TwoWay}"
|
||||
ToolTip.Tip="{CompiledBinding DecryptToLossyTip}">
|
||||
IsChecked="{Binding !DecryptToLossy, Mode=TwoWay}"
|
||||
ToolTip.Tip="{Binding DecryptToLossyTip}">
|
||||
|
||||
<StackPanel VerticalAlignment="Center">
|
||||
<TextBlock
|
||||
Text="Download my books in the original audio format (Lossless)" />
|
||||
<CheckBox
|
||||
IsEnabled="{CompiledBinding !DecryptToLossy}"
|
||||
IsChecked="{CompiledBinding MoveMoovToBeginning, Mode=TwoWay}"
|
||||
ToolTip.Tip="{CompiledBinding MoveMoovToBeginningTip}">
|
||||
<TextBlock Text="{CompiledBinding MoveMoovToBeginningText}" />
|
||||
IsEnabled="{Binding !DecryptToLossy}"
|
||||
IsChecked="{Binding MoveMoovToBeginning, Mode=TwoWay}"
|
||||
ToolTip.Tip="{Binding MoveMoovToBeginningTip}">
|
||||
<TextBlock Text="{Binding MoveMoovToBeginningText}" />
|
||||
</CheckBox>
|
||||
</StackPanel>
|
||||
</RadioButton>
|
||||
|
||||
<RadioButton
|
||||
IsChecked="{CompiledBinding DecryptToLossy, Mode=TwoWay}"
|
||||
ToolTip.Tip="{CompiledBinding DecryptToLossyTip}">
|
||||
IsChecked="{Binding DecryptToLossy, Mode=TwoWay}"
|
||||
ToolTip.Tip="{Binding DecryptToLossyTip}">
|
||||
<TextBlock
|
||||
TextWrapping="Wrap"
|
||||
Text="Download my books as .MP3 files (transcode if necessary)" />
|
||||
@@ -203,7 +226,7 @@
|
||||
|
||||
<controls:GroupBox
|
||||
Grid.Column="1"
|
||||
IsEnabled="{CompiledBinding DecryptToLossy}"
|
||||
IsEnabled="{Binding DecryptToLossy}"
|
||||
Label="Mp3 Encoding Options">
|
||||
|
||||
<Grid RowDefinitions="Auto,Auto,Auto,Auto,*">
|
||||
@@ -220,21 +243,21 @@
|
||||
<RadioButton
|
||||
Margin="5"
|
||||
Content="Bitrate"
|
||||
IsChecked="{CompiledBinding LameTargetBitrate, Mode=TwoWay}"/>
|
||||
IsChecked="{Binding LameTargetBitrate, Mode=TwoWay}"/>
|
||||
|
||||
<RadioButton
|
||||
Grid.Column="1"
|
||||
Margin="5"
|
||||
Content="Quality"
|
||||
IsChecked="{CompiledBinding !LameTargetBitrate, Mode=TwoWay}"/>
|
||||
IsChecked="{Binding !LameTargetBitrate, Mode=TwoWay}"/>
|
||||
</Grid>
|
||||
</controls:GroupBox>
|
||||
|
||||
<CheckBox
|
||||
HorizontalAlignment="Right"
|
||||
Grid.Column="1"
|
||||
IsChecked="{CompiledBinding LameDownsampleMono, Mode=TwoWay}"
|
||||
ToolTip.Tip="{CompiledBinding LameDownsampleMonoTip}">
|
||||
IsChecked="{Binding LameDownsampleMono, Mode=TwoWay}"
|
||||
ToolTip.Tip="{Binding LameDownsampleMonoTip}">
|
||||
|
||||
<TextBlock
|
||||
TextWrapping="Wrap"
|
||||
@@ -249,8 +272,8 @@
|
||||
<controls:WheelComboBox
|
||||
Grid.Row="1"
|
||||
HorizontalAlignment="Stretch"
|
||||
ItemsSource="{CompiledBinding SampleRates}"
|
||||
SelectedItem="{CompiledBinding SelectedSampleRate, Mode=TwoWay}"/>
|
||||
ItemsSource="{Binding SampleRates}"
|
||||
SelectedItem="{Binding SelectedSampleRate, Mode=TwoWay}"/>
|
||||
|
||||
<TextBlock Margin="0,0,0,5" Grid.Column="2" Text="Encoder Quality:" />
|
||||
|
||||
@@ -258,23 +281,23 @@
|
||||
Grid.Column="2"
|
||||
Grid.Row="1"
|
||||
HorizontalAlignment="Stretch"
|
||||
ItemsSource="{CompiledBinding EncoderQualities}"
|
||||
SelectedItem="{CompiledBinding SelectedEncoderQuality, Mode=TwoWay}"/>
|
||||
ItemsSource="{Binding EncoderQualities}"
|
||||
SelectedItem="{Binding SelectedEncoderQuality, Mode=TwoWay}"/>
|
||||
</Grid>
|
||||
|
||||
<controls:GroupBox
|
||||
Grid.Row="2"
|
||||
Margin="0,5"
|
||||
Label="Bitrate"
|
||||
IsEnabled="{CompiledBinding LameTargetBitrate}" >
|
||||
IsEnabled="{Binding LameTargetBitrate}" >
|
||||
|
||||
<StackPanel>
|
||||
<Grid ColumnDefinitions="*,25,Auto">
|
||||
|
||||
<Slider
|
||||
Grid.Column="0"
|
||||
IsEnabled="{CompiledBinding !LameMatchSource}"
|
||||
Value="{CompiledBinding LameBitrate, Mode=TwoWay}"
|
||||
IsEnabled="{Binding !LameMatchSource}"
|
||||
Value="{Binding LameBitrate, Mode=TwoWay}"
|
||||
Minimum="16"
|
||||
Maximum="320"
|
||||
IsSnapToTickEnabled="True" TickFrequency="16"
|
||||
@@ -283,7 +306,7 @@
|
||||
|
||||
<Slider.Styles>
|
||||
<Style Selector="Slider /template/ Thumb">
|
||||
<Setter Property="ToolTip.Tip" Value="{CompiledBinding $parent[Slider].Value, Mode=OneWay, StringFormat='\{0:f0\} Kbps'}" />
|
||||
<Setter Property="ToolTip.Tip" Value="{Binding $parent[Slider].Value, Mode=OneWay, StringFormat='\{0:f0\} Kbps'}" />
|
||||
<Setter Property="ToolTip.Placement" Value="Top" />
|
||||
<Setter Property="ToolTip.VerticalOffset" Value="-10" />
|
||||
<Setter Property="ToolTip.HorizontalOffset" Value="-30" />
|
||||
@@ -294,7 +317,7 @@
|
||||
<TextBlock
|
||||
Grid.Column="1"
|
||||
HorizontalAlignment="Right"
|
||||
Text="{CompiledBinding LameBitrate}" />
|
||||
Text="{Binding LameBitrate}" />
|
||||
|
||||
<TextBlock
|
||||
Grid.Column="2"
|
||||
@@ -306,7 +329,7 @@
|
||||
|
||||
<CheckBox
|
||||
Grid.Column="0"
|
||||
IsChecked="{CompiledBinding LameConstantBitrate, Mode=TwoWay}">
|
||||
IsChecked="{Binding LameConstantBitrate, Mode=TwoWay}">
|
||||
|
||||
<TextBlock
|
||||
TextWrapping="Wrap"
|
||||
@@ -317,7 +340,7 @@
|
||||
<CheckBox
|
||||
Grid.Column="1"
|
||||
HorizontalAlignment="Right"
|
||||
IsChecked="{CompiledBinding LameMatchSource, Mode=TwoWay}">
|
||||
IsChecked="{Binding LameMatchSource, Mode=TwoWay}">
|
||||
|
||||
<TextBlock
|
||||
TextWrapping="Wrap"
|
||||
@@ -332,7 +355,7 @@
|
||||
Grid.Row="3"
|
||||
Margin="0,5"
|
||||
Label="Quality"
|
||||
IsEnabled="{CompiledBinding !LameTargetBitrate}">
|
||||
IsEnabled="{Binding !LameTargetBitrate}">
|
||||
|
||||
<Grid
|
||||
ColumnDefinitions="*,Auto,25"
|
||||
@@ -341,7 +364,7 @@
|
||||
<Slider
|
||||
Grid.Column="0"
|
||||
Grid.ColumnSpan="2"
|
||||
Value="{CompiledBinding LameVBRQuality, Mode=TwoWay}"
|
||||
Value="{Binding LameVBRQuality, Mode=TwoWay}"
|
||||
Minimum="0"
|
||||
Maximum="9"
|
||||
IsSnapToTickEnabled="True" TickFrequency="1"
|
||||
@@ -349,7 +372,7 @@
|
||||
TickPlacement="Outside">
|
||||
<Slider.Styles>
|
||||
<Style Selector="Slider /template/ Thumb">
|
||||
<Setter Property="ToolTip.Tip" Value="{CompiledBinding $parent[Slider].Value, Mode=OneWay, StringFormat='V\{0:f0\}'}" />
|
||||
<Setter Property="ToolTip.Tip" Value="{Binding $parent[Slider].Value, Mode=OneWay, StringFormat='V\{0:f0\}'}" />
|
||||
<Setter Property="ToolTip.Placement" Value="Top" />
|
||||
<Setter Property="ToolTip.VerticalOffset" Value="-10" />
|
||||
<Setter Property="ToolTip.HorizontalOffset" Value="-30" />
|
||||
@@ -363,7 +386,7 @@
|
||||
Orientation="Horizontal">
|
||||
|
||||
<TextBlock Text="V" />
|
||||
<TextBlock Text="{CompiledBinding LameVBRQuality}" />
|
||||
<TextBlock Text="{Binding LameVBRQuality}" />
|
||||
|
||||
</StackPanel>
|
||||
|
||||
@@ -397,8 +420,8 @@
|
||||
Grid.Row="2"
|
||||
Grid.ColumnSpan="2"
|
||||
Margin="0,10,0,0"
|
||||
IsEnabled="{CompiledBinding SplitFilesByChapter}"
|
||||
Label="{CompiledBinding ChapterTitleTemplateText}">
|
||||
IsEnabled="{Binding SplitFilesByChapter}"
|
||||
Label="{Binding ChapterTitleTemplateText}">
|
||||
|
||||
<Grid ColumnDefinitions="*,Auto" Margin="0,8" >
|
||||
|
||||
@@ -406,7 +429,7 @@
|
||||
Grid.Column="0"
|
||||
FontSize="14"
|
||||
IsReadOnly="True"
|
||||
Text="{CompiledBinding ChapterTitleTemplate}" />
|
||||
Text="{Binding ChapterTitleTemplate}" />
|
||||
|
||||
<Button
|
||||
Grid.Column="1"
|
||||
|
||||
@@ -39,6 +39,7 @@ namespace LibationAvalonia.ViewModels.Settings
|
||||
DownloadClipsBookmarks = config.DownloadClipsBookmarks;
|
||||
ClipBookmarkFormat = config.ClipsBookmarksFileFormat;
|
||||
SplitFilesByChapter = config.SplitFilesByChapter;
|
||||
MinimumFileDuration = config.MinimumFileDuration;
|
||||
MergeOpeningAndEndCredits = config.MergeOpeningAndEndCredits;
|
||||
StripAudibleBrandAudio = config.StripAudibleBrandAudio;
|
||||
StripUnabridged = config.StripUnabridged;
|
||||
@@ -71,6 +72,7 @@ namespace LibationAvalonia.ViewModels.Settings
|
||||
config.DownloadClipsBookmarks = DownloadClipsBookmarks;
|
||||
config.ClipsBookmarksFileFormat = ClipBookmarkFormat;
|
||||
config.SplitFilesByChapter = SplitFilesByChapter;
|
||||
config.MinimumFileDuration = MinimumFileDuration;
|
||||
config.MergeOpeningAndEndCredits = MergeOpeningAndEndCredits;
|
||||
config.StripAudibleBrandAudio = StripAudibleBrandAudio;
|
||||
config.StripUnabridged = StripUnabridged;
|
||||
@@ -118,6 +120,7 @@ namespace LibationAvalonia.ViewModels.Settings
|
||||
public string DownloadCoverArtText { get; } = Configuration.GetDescription(nameof(Configuration.DownloadCoverArt));
|
||||
public string RetainAaxFileText { get; } = Configuration.GetDescription(nameof(Configuration.RetainAaxFile));
|
||||
public string SplitFilesByChapterText { get; } = Configuration.GetDescription(nameof(Configuration.SplitFilesByChapter));
|
||||
public string MinimumFileDurationText { get; } = Configuration.GetDescription(nameof(Configuration.MinimumFileDuration));
|
||||
public string MergeOpeningEndCreditsText { get; } = Configuration.GetDescription(nameof(Configuration.MergeOpeningAndEndCredits));
|
||||
public string StripAudibleBrandingText { get; } = Configuration.GetDescription(nameof(Configuration.StripAudibleBrandAudio));
|
||||
public string StripUnabridgedText { get; } = Configuration.GetDescription(nameof(Configuration.StripUnabridged));
|
||||
@@ -146,6 +149,7 @@ namespace LibationAvalonia.ViewModels.Settings
|
||||
public string StripUnabridgedTip => Configuration.GetHelpText(nameof(StripUnabridged));
|
||||
public bool DecryptToLossy { get => field; set => this.RaiseAndSetIfChanged(ref field, value); }
|
||||
public string DecryptToLossyTip => Configuration.GetHelpText(nameof(DecryptToLossy));
|
||||
public string MinimumFileDurationTip => Configuration.GetHelpText(nameof(MinimumFileDuration));
|
||||
public bool MoveMoovToBeginning { get; set; }
|
||||
|
||||
public bool LameDownsampleMono { get; set; } = Design.IsDesignMode;
|
||||
@@ -153,6 +157,7 @@ namespace LibationAvalonia.ViewModels.Settings
|
||||
public bool LameConstantBitrate { get; set; } = Design.IsDesignMode;
|
||||
|
||||
public bool SplitFilesByChapter { get => field; set { this.RaiseAndSetIfChanged(ref field, value); } }
|
||||
public int MinimumFileDuration { get => field; set { this.RaiseAndSetIfChanged(ref field, value); } }
|
||||
public bool LameTargetBitrate { get => field; set { this.RaiseAndSetIfChanged(ref field, value); } }
|
||||
public bool LameMatchSource { get => field; set { this.RaiseAndSetIfChanged(ref field, value); } }
|
||||
public int LameBitrate { get => field; set { this.RaiseAndSetIfChanged(ref field, value); } }
|
||||
|
||||
@@ -58,7 +58,10 @@
|
||||
</StackPanel.Styles>
|
||||
<TextBlock Margin="0,0,6,0" FontSize="11" Text="DL
Limit" VerticalAlignment="Center" />
|
||||
<NumericUpDown
|
||||
Classes="SmallNumericUpDown"
|
||||
MinWidth="100"
|
||||
FontSize="12"
|
||||
HorizontalContentAlignment="Center"
|
||||
VerticalContentAlignment="Center"
|
||||
TextConverter="{StaticResource myConverter}"
|
||||
Height="{Binding #cancelAllBtn.DesiredSize.Height}"
|
||||
|
||||
@@ -82,6 +82,13 @@ namespace LibationFileManager
|
||||
from the decrypted audiobook. This does not require
|
||||
re-encoding.
|
||||
""" },
|
||||
{nameof(MinimumFileDuration), """
|
||||
The minimum duration (in minutes) for an chapter to
|
||||
be split into its own file. Chapters shorter than
|
||||
this duration will be merged with the following
|
||||
chapter. Merged chapter titles will be joined with
|
||||
a space between them.
|
||||
""" },
|
||||
{nameof(SpatialAudioCodec), """
|
||||
The Dolby Digital Plus (E-AC-3) codec is more widely
|
||||
supported than the AC-4 codec, but E-AC-3 files are
|
||||
|
||||
@@ -169,6 +169,9 @@ namespace LibationFileManager
|
||||
[Description("Split my books into multiple files by chapter")]
|
||||
public bool SplitFilesByChapter { get => GetNonString(defaultValue: false); set => SetNonString(value); }
|
||||
|
||||
[Description("Minimum file duration (seconds)")]
|
||||
public int MinimumFileDuration { get => Math.Max(0, GetNonString(defaultValue: 3)); set => SetNonString(value); }
|
||||
|
||||
[Description("Merge Opening/End Credits into the following/preceding chapters")]
|
||||
public bool MergeOpeningAndEndCredits { get => GetNonString(defaultValue: false); set => SetNonString(value); }
|
||||
|
||||
|
||||
@@ -19,6 +19,7 @@ namespace LibationWinForms.Dialogs
|
||||
this.retainAaxFileCbox.Text = desc(nameof(config.RetainAaxFile));
|
||||
this.combineNestedChapterTitlesCbox.Text = desc(nameof(config.CombineNestedChapterTitles));
|
||||
this.splitFilesByChapterCbox.Text = desc(nameof(config.SplitFilesByChapter));
|
||||
this.minFileDurationLbl.Text = desc(nameof(config.MinimumFileDuration));
|
||||
this.mergeOpeningEndCreditsCbox.Text = desc(nameof(config.MergeOpeningAndEndCredits));
|
||||
this.stripAudibleBrandingCbox.Text = desc(nameof(config.StripAudibleBrandAudio));
|
||||
this.stripUnabridgedCbox.Text = desc(nameof(config.StripUnabridged));
|
||||
@@ -40,6 +41,8 @@ namespace LibationWinForms.Dialogs
|
||||
toolTip.SetToolTip(requestSpatialCbox, Configuration.GetHelpText(nameof(config.RequestSpatial)));
|
||||
toolTip.SetToolTip(request_xHE_AAC_Cbox, Configuration.GetHelpText(nameof(config.Request_xHE_AAC)));
|
||||
toolTip.SetToolTip(spatialAudioCodecCb, Configuration.GetHelpText(nameof(config.SpatialAudioCodec)));
|
||||
toolTip.SetToolTip(minFileDurationLbl, Configuration.GetHelpText(nameof(config.SpatialAudioCodec)));
|
||||
toolTip.SetToolTip(minFileDurationNud, Configuration.GetHelpText(nameof(config.SpatialAudioCodec)));
|
||||
|
||||
fileDownloadQualityCb.Items.AddRange(
|
||||
[
|
||||
@@ -87,6 +90,7 @@ namespace LibationWinForms.Dialogs
|
||||
retainAaxFileCbox.Checked = config.RetainAaxFile;
|
||||
combineNestedChapterTitlesCbox.Checked = config.CombineNestedChapterTitles;
|
||||
splitFilesByChapterCbox.Checked = config.SplitFilesByChapter;
|
||||
minFileDurationNud.Value = config.MinimumFileDuration;
|
||||
mergeOpeningEndCreditsCbox.Checked = config.MergeOpeningAndEndCredits;
|
||||
stripUnabridgedCbox.Checked = config.StripUnabridged;
|
||||
stripAudibleBrandingCbox.Checked = config.StripAudibleBrandAudio;
|
||||
@@ -132,6 +136,7 @@ namespace LibationWinForms.Dialogs
|
||||
config.RetainAaxFile = retainAaxFileCbox.Checked;
|
||||
config.CombineNestedChapterTitles = combineNestedChapterTitlesCbox.Checked;
|
||||
config.SplitFilesByChapter = splitFilesByChapterCbox.Checked;
|
||||
config.MinimumFileDuration = (int)minFileDurationNud.Value;
|
||||
config.MergeOpeningAndEndCredits = mergeOpeningEndCreditsCbox.Checked;
|
||||
config.StripUnabridged = stripUnabridgedCbox.Checked;
|
||||
config.StripAudibleBrandAudio = stripAudibleBrandingCbox.Checked;
|
||||
@@ -167,7 +172,7 @@ namespace LibationWinForms.Dialogs
|
||||
|
||||
private void splitFilesByChapterCbox_CheckedChanged(object sender, EventArgs e)
|
||||
{
|
||||
chapterTitleTemplateGb.Enabled = splitFilesByChapterCbox.Checked;
|
||||
chapterTitleTemplateGb.Enabled = minFileDurationNud.Enabled = minFileDurationLbl.Enabled = splitFilesByChapterCbox.Checked;
|
||||
}
|
||||
|
||||
private void chapterTitleTemplateBtn_Click(object sender, EventArgs e)
|
||||
|
||||
@@ -99,6 +99,8 @@
|
||||
clipsBookmarksFormatCb = new System.Windows.Forms.ComboBox();
|
||||
downloadClipsBookmarksCbox = new System.Windows.Forms.CheckBox();
|
||||
audiobookFixupsGb = new System.Windows.Forms.GroupBox();
|
||||
minFileDurationLbl = new System.Windows.Forms.Label();
|
||||
minFileDurationNud = new System.Windows.Forms.NumericUpDown();
|
||||
stripUnabridgedCbox = new System.Windows.Forms.CheckBox();
|
||||
chapterTitleTemplateGb = new System.Windows.Forms.GroupBox();
|
||||
chapterTitleTemplateBtn = new System.Windows.Forms.Button();
|
||||
@@ -154,6 +156,7 @@
|
||||
customFileNamingGb.SuspendLayout();
|
||||
tab4AudioFileOptions.SuspendLayout();
|
||||
audiobookFixupsGb.SuspendLayout();
|
||||
((System.ComponentModel.ISupportInitialize)minFileDurationNud).BeginInit();
|
||||
chapterTitleTemplateGb.SuspendLayout();
|
||||
lameOptionsGb.SuspendLayout();
|
||||
lameBitrateGb.SuspendLayout();
|
||||
@@ -289,7 +292,7 @@
|
||||
// stripAudibleBrandingCbox
|
||||
//
|
||||
stripAudibleBrandingCbox.AutoSize = true;
|
||||
stripAudibleBrandingCbox.Location = new System.Drawing.Point(13, 70);
|
||||
stripAudibleBrandingCbox.Location = new System.Drawing.Point(13, 88);
|
||||
stripAudibleBrandingCbox.Name = "stripAudibleBrandingCbox";
|
||||
stripAudibleBrandingCbox.Size = new System.Drawing.Size(143, 34);
|
||||
stripAudibleBrandingCbox.TabIndex = 16;
|
||||
@@ -960,20 +963,41 @@
|
||||
//
|
||||
// audiobookFixupsGb
|
||||
//
|
||||
audiobookFixupsGb.Controls.Add(minFileDurationLbl);
|
||||
audiobookFixupsGb.Controls.Add(minFileDurationNud);
|
||||
audiobookFixupsGb.Controls.Add(splitFilesByChapterCbox);
|
||||
audiobookFixupsGb.Controls.Add(stripUnabridgedCbox);
|
||||
audiobookFixupsGb.Controls.Add(stripAudibleBrandingCbox);
|
||||
audiobookFixupsGb.Location = new System.Drawing.Point(6, 254);
|
||||
audiobookFixupsGb.Name = "audiobookFixupsGb";
|
||||
audiobookFixupsGb.Size = new System.Drawing.Size(416, 114);
|
||||
audiobookFixupsGb.Size = new System.Drawing.Size(416, 128);
|
||||
audiobookFixupsGb.TabIndex = 14;
|
||||
audiobookFixupsGb.TabStop = false;
|
||||
audiobookFixupsGb.Text = "Audiobook Fix-ups";
|
||||
//
|
||||
// minFileDurationLbl
|
||||
//
|
||||
minFileDurationLbl.AutoSize = true;
|
||||
minFileDurationLbl.Location = new System.Drawing.Point(34, 44);
|
||||
minFileDurationLbl.Margin = new System.Windows.Forms.Padding(0, 0, 2, 0);
|
||||
minFileDurationLbl.Name = "minFileDurationLbl";
|
||||
minFileDurationLbl.Size = new System.Drawing.Size(159, 15);
|
||||
minFileDurationLbl.TabIndex = 29;
|
||||
minFileDurationLbl.Text = "[MinimumFileDuration desc]";
|
||||
//
|
||||
// minFileDurationNud
|
||||
//
|
||||
minFileDurationNud.Location = new System.Drawing.Point(243, 41);
|
||||
minFileDurationNud.Maximum = new decimal(new int[] { 120, 0, 0, 0 });
|
||||
minFileDurationNud.Name = "minFileDurationNud";
|
||||
minFileDurationNud.Size = new System.Drawing.Size(51, 23);
|
||||
minFileDurationNud.TabIndex = 17;
|
||||
minFileDurationNud.TextAlign = System.Windows.Forms.HorizontalAlignment.Center;
|
||||
//
|
||||
// stripUnabridgedCbox
|
||||
//
|
||||
stripUnabridgedCbox.AutoSize = true;
|
||||
stripUnabridgedCbox.Location = new System.Drawing.Point(13, 46);
|
||||
stripUnabridgedCbox.Location = new System.Drawing.Point(13, 63);
|
||||
stripUnabridgedCbox.Name = "stripUnabridgedCbox";
|
||||
stripUnabridgedCbox.Size = new System.Drawing.Size(147, 19);
|
||||
stripUnabridgedCbox.TabIndex = 15;
|
||||
@@ -1498,6 +1522,7 @@
|
||||
tab4AudioFileOptions.PerformLayout();
|
||||
audiobookFixupsGb.ResumeLayout(false);
|
||||
audiobookFixupsGb.PerformLayout();
|
||||
((System.ComponentModel.ISupportInitialize)minFileDurationNud).EndInit();
|
||||
chapterTitleTemplateGb.ResumeLayout(false);
|
||||
chapterTitleTemplateGb.PerformLayout();
|
||||
lameOptionsGb.ResumeLayout(false);
|
||||
@@ -1627,5 +1652,7 @@
|
||||
private System.Windows.Forms.ComboBox themeCb;
|
||||
private System.Windows.Forms.Label themeLbl;
|
||||
private System.Windows.Forms.CheckBox importPlusTitlesCb;
|
||||
private System.Windows.Forms.Label minFileDurationLbl;
|
||||
private System.Windows.Forms.NumericUpDown minFileDurationNud;
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user