Skip to content

Commit

Permalink
Added srt export feature
Browse files Browse the repository at this point in the history
  • Loading branch information
EX3exp committed Sep 28, 2024
1 parent b94c44a commit 3b67d42
Show file tree
Hide file tree
Showing 8 changed files with 97 additions and 8 deletions.
5 changes: 4 additions & 1 deletion Mirivoice/Assets/Lang/strings-en-US.axaml
Original file line number Diff line number Diff line change
Expand Up @@ -44,8 +44,11 @@
An Error occured during export.
Please Check Log file for more informations.</system:String>
<system:String x:Key="menu.files.export.perLine.desc">Select Directory to export</system:String>
<system:String x:Key="menu.files.export.merged">Export audio merged (.wav)</system:String>
<system:String x:Key="menu.files.export.merged">Export merged audio (.wav)</system:String>
<system:String x:Key="menu.files.export.merged.desc">Set Filename to export</system:String>

<system:String x:Key="menu.files.export.srt">Export SubRip Text for merged audio (.srt)</system:String>
<system:String x:Key="menu.files.export.srt.desc">Set Filename to export</system:String>


<!--project...-->
Expand Down
56 changes: 53 additions & 3 deletions Mirivoice/Mirivoice.Core/Managers/AudioManager.cs
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@
using System.Collections.ObjectModel;
using System.IO;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using Mirivoice.ViewModels;
using Mirivoice.Views;
Expand Down Expand Up @@ -62,7 +63,13 @@ string SetSuffixToUnique(string filepath, int suffix)
}
else return filepath;
}

public TimeSpan GetAudioDuration(string audioFilePath)
{
using (var reader = new AudioFileReader(audioFilePath))
{
return reader.TotalTime;
}
}
List<string> GetAllCacheFiles()
{
return Directory.GetFiles(MainManager.Instance.PathM.CachePath, "*.wav").ToList();
Expand All @@ -79,7 +86,7 @@ List<string> GetAllCacheFiles()
/// <param name="exportPerTrack"></param>
/// <param name="fileName"></param>
/// <param name="DirPath"></param>
public async void PlayAllCacheFiles(int startIndex, bool exportOnlyAndDoNotPlay=false, bool exportPerTrack=true, string fileName="", string DirPath="")
public async void PlayAllCacheFiles(int startIndex, bool exportOnlyAndDoNotPlay=false, bool exportPerTrack=true, string fileName="", string DirPath="", bool exportSrtInsteadOfAudio = false)
{
MainViewModelPlaying = true;
if ( _waveOut != null && _waveOut.PlaybackState == PlaybackState.Paused)
Expand All @@ -88,16 +95,22 @@ public async void PlayAllCacheFiles(int startIndex, bool exportOnlyAndDoNotPlay=
return;
}
List<string> caches = new List<string>();
List<string> lines = new List<string>();
List<string> voicerNames = new List<string>();

int index = 0;
v.SingleTextBoxEditorEnabled = false;
v.CurrentEdit.IsEnabled = false;
var tasks = new List<Task>();

caches.Clear();
lines.Clear();
voicerNames.Clear();
for (int i = startIndex - 1; i < v.LineBoxCollection.Count; ++i)
{
caches.Add(v.LineBoxCollection[i].CurrentCacheName);
lines.Add(v.LineBoxCollection[i].viewModel.LineText);
voicerNames.Add(v.LineBoxCollection[i].viewModel.voicerSelector.CurrentVoicer.Info.Name);
}
v.MainWindowGetInput = false;
for (int i = 0; i < v.LineBoxCollection.Count; ++i)
Expand Down Expand Up @@ -165,8 +178,45 @@ public async void PlayAllCacheFiles(int startIndex, bool exportOnlyAndDoNotPlay=
}
else
{
string exportPath;
// export srt for mixdown
if (exportSrtInsteadOfAudio)
{
exportPath = Path.Combine(DirPath, $"{fileName}.srt"); // for srt with line texts
string exportPathNamesSrt = Path.Combine(DirPath, $"{fileName}-voicer names.srt"); // for srt with voicer names
exportPath = SetSuffixToUnique(exportPath, 1);
exportPathNamesSrt = SetSuffixToUnique(exportPathNamesSrt, 1);

TimeSpan lastTs = TimeSpan.Zero;
StringBuilder sb1 = new StringBuilder();
StringBuilder sb2 = new StringBuilder();
for (int i = 0; i < caches.Count; ++i)
{
sb1.AppendLine((i + 1).ToString());
sb2.AppendLine((i + 1).ToString());
TimeSpan currTs = GetAudioDuration(caches[i]);

string lastTime = lastTs.ToString(@"hh\:mm\:ss\,fff");
string currTime = currTs.ToString(@"hh\:mm\:ss\,fff");
sb1.AppendLine($"{lastTime} --> {currTime}"); // hours:minutes:seconds,milliseconds (00:00:00,000)
sb2.AppendLine($"{lastTime} --> {currTime}");
sb1.AppendLine(lines[i]);
sb2.AppendLine(voicerNames[i]);
sb1.AppendLine();
sb2.AppendLine();



lastTs = currTs;
}
File.WriteAllText(exportPath, sb1.ToString());
File.WriteAllText(exportPathNamesSrt, sb2.ToString());

return;
}

// export mixdown
string exportPath = Path.Combine(DirPath, $"{fileName}.wav");
exportPath = Path.Combine(DirPath, $"{fileName}.wav");
exportPath = SetSuffixToUnique(exportPath, 1);
using (var outputWaveFile = new WaveFileWriter(exportPath, new WaveFormat(48000, 1)))
{
Expand Down
34 changes: 34 additions & 0 deletions Mirivoice/ViewModels/MainViewModel.cs
Original file line number Diff line number Diff line change
Expand Up @@ -40,6 +40,10 @@ public class MainViewModel : VoicerSelectingViewModelBase
Patterns = new[] { "*.wav" }
};

public static FilePickerFileType MiriVoiceExportSubRip { get; } = new("SubRip File")
{
Patterns = new[] { "*.srt" }
};
public static FilePickerFileType MiriVoiceVoicer { get; } = new("Zip File")
{
Patterns = new[] { "*.zip" }
Expand Down Expand Up @@ -816,6 +820,36 @@ public void OnVoicersButtonClick()
window.Show();
}

public async void OnExportSrtClick()
{
if (LineBoxCollection.Count == 0)
{
return;
}
var topLevel = TopLevel.GetTopLevel(mainWindow);
var file = await topLevel.StorageProvider.SaveFilePickerAsync(new FilePickerSaveOptions
{
Title = (string)mainWindow.FindResource("menu.files.export.srt.desc"),
DefaultExtension = "srt",
ShowOverwritePrompt = true,
FileTypeChoices = new[] { MiriVoiceExportSubRip },
SuggestedFileName = System.IO.Path.GetFileNameWithoutExtension(CurrentProjectPath) + ".srt"
});

if (file is not null)
{
string path = file.Path.LocalPath;
try
{
MainManager.Instance.AudioM.PlayAllCacheFiles(1, true, false, System.IO.Path.GetFileNameWithoutExtension(path), System.IO.Path.GetDirectoryName(path), true);
}
catch (Exception e)
{
Log.Error($"[Failed to export srt for merged audio]{e.ToString}: {e.Message} \n>> traceback: \n\t{e.StackTrace}");
var res = await ShowConfirmWindow("menu.files.export.failed");
}
}
}
public async void OnVoicerInstallButtonClick()
{
VoicerInstaller voicerInstaller = new VoicerInstaller(this);
Expand Down
2 changes: 1 addition & 1 deletion Mirivoice/ViewModels/ViewModelBase.cs
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@ public class ViewModelBase : ReactiveObject, INotifyPropertyChanged
public event PropertyChangedEventHandler PropertyChanged;

Check warning on line 9 in Mirivoice/ViewModels/ViewModelBase.cs

View workflow job for this annotation

GitHub Actions / build (win-x64)

'ViewModelBase.PropertyChanged' hides inherited member 'ReactiveObject.PropertyChanged'. Use the new keyword if hiding was intended.

Check warning on line 9 in Mirivoice/ViewModels/ViewModelBase.cs

View workflow job for this annotation

GitHub Actions / build (win-x64)

Nullability of reference types in type of 'event PropertyChangedEventHandler ViewModelBase.PropertyChanged' doesn't match implicitly implemented member 'event PropertyChangedEventHandler? INotifyPropertyChanged.PropertyChanged'.

Check warning on line 9 in Mirivoice/ViewModels/ViewModelBase.cs

View workflow job for this annotation

GitHub Actions / build (linux-x64)

'ViewModelBase.PropertyChanged' hides inherited member 'ReactiveObject.PropertyChanged'. Use the new keyword if hiding was intended.

Check warning on line 9 in Mirivoice/ViewModels/ViewModelBase.cs

View workflow job for this annotation

GitHub Actions / build (linux-x64)

Nullability of reference types in type of 'event PropertyChangedEventHandler ViewModelBase.PropertyChanged' doesn't match implicitly implemented member 'event PropertyChangedEventHandler? INotifyPropertyChanged.PropertyChanged'.

Check warning on line 9 in Mirivoice/ViewModels/ViewModelBase.cs

View workflow job for this annotation

GitHub Actions / build (osx-x64)

'ViewModelBase.PropertyChanged' hides inherited member 'ReactiveObject.PropertyChanged'. Use the new keyword if hiding was intended.

Check warning on line 9 in Mirivoice/ViewModels/ViewModelBase.cs

View workflow job for this annotation

GitHub Actions / build (osx-x64)

Nullability of reference types in type of 'event PropertyChangedEventHandler ViewModelBase.PropertyChanged' doesn't match implicitly implemented member 'event PropertyChangedEventHandler? INotifyPropertyChanged.PropertyChanged'.
public virtual void OnPropertyChanged(string propertyName)
{
Log.Debug("[Property Changed]: {propertyName}", propertyName);
//Log.Debug("[Property Changed]: {propertyName}", propertyName);
PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(propertyName));
}
}
1 change: 0 additions & 1 deletion Mirivoice/ViewModels/VoicersVoicerButtonViewModel.cs
Original file line number Diff line number Diff line change
Expand Up @@ -105,7 +105,6 @@ public void OnButtonClick()
foreach (var meta in voicerMetas )
{
Log.Debug($"VoicerMeta {i}: {meta.Style}");
Voicer.CurrentVoicerMeta = meta;
voicersStyleBoxes.Add(new VoicersStyleBox(Voicer, i, mv));
++i;
}
Expand Down
2 changes: 2 additions & 0 deletions Mirivoice/Views/MainView.axaml
Original file line number Diff line number Diff line change
Expand Up @@ -36,6 +36,8 @@
<MenuItem Header="{DynamicResource menu.files.export}">
<MenuItem Header="{DynamicResource menu.files.export.perLine}" Command="{Binding OnExportAudioPerLineClick}"></MenuItem>
<MenuItem Header="{DynamicResource menu.files.export.merged}" Command="{Binding OnExportAudioMergedClick}"></MenuItem>
<Separator/>
<MenuItem Header="{DynamicResource menu.files.export.srt}" Command="{Binding OnExportSrtClick}"></MenuItem>
</MenuItem>

</MenuItem>
Expand Down
4 changes: 2 additions & 2 deletions Mirivoice/Views/VoicersStyleBox.axaml
Original file line number Diff line number Diff line change
Expand Up @@ -20,9 +20,9 @@
</StackPanel>
</ScrollViewer>

<ToggleButton Focusable="False" Cursor="Hand" Grid.Row="0" Click="OnSamplePlayButtonClick" Background="DarkOliveGreen" Width="44" Height="54">
<Button Focusable="False" Cursor="Hand" Grid.Row="0" Click="OnSamplePlayButtonClick" Background="DarkOliveGreen" Width="44" Height="54">
<Path Data="{StaticResource speaker_regular}" Fill="Wheat" Stretch="Uniform" HorizontalAlignment="Center" VerticalAlignment="Center"/>
</ToggleButton>
</Button>

</StackPanel>

Expand Down
1 change: 1 addition & 0 deletions Mirivoice/Views/VoicersStyleBox.axaml.cs
Original file line number Diff line number Diff line change
Expand Up @@ -56,6 +56,7 @@ public async void OnSamplePlayButtonClick(object sender, RoutedEventArgs e)
if (File.Exists(cachePath))
{
isPlaying = true;
v.PlayAudio(cachePath);
return;
}
if (voicer != null)
Expand Down

0 comments on commit 3b67d42

Please sign in to comment.