Fixes ASS converter, adds some doc
This commit is contained in:
197
.idea/workspace.xml
generated
197
.idea/workspace.xml
generated
@@ -5,138 +5,11 @@
|
||||
</component>
|
||||
<component name="ChangeListManager">
|
||||
<list default="true" id="b9d7e333-acad-414e-8be1-4685e71ee4fe" name="Changes" comment="">
|
||||
<change afterPath="$PROJECT_DIR$/.idea/uiDesigner.xml" afterDir="false" />
|
||||
<change afterPath="$PROJECT_DIR$/core/src/main/java/com/github/gtache/autosubtitle/modules/impl/ToolTypeKey.java" afterDir="false" />
|
||||
<change afterPath="$PROJECT_DIR$/core/src/main/java/com/github/gtache/autosubtitle/modules/setup/impl/VideoLoaderSetup.java" afterDir="false" />
|
||||
<change beforePath="$PROJECT_DIR$/.idea/workspace.xml" beforeDir="false" afterPath="$PROJECT_DIR$/.idea/workspace.xml" afterDir="false" />
|
||||
<change beforePath="$PROJECT_DIR$/api/src/main/java/com/github/gtache/autosubtitle/ToolType.java" beforeDir="false" afterPath="$PROJECT_DIR$/api/src/main/java/com/github/gtache/autosubtitle/ToolType.java" afterDir="false" />
|
||||
<change beforePath="$PROJECT_DIR$/conda/src/main/java/com/github/gtache/autosubtitle/modules/setup/conda/CondaBundledPath.java" beforeDir="false" afterPath="$PROJECT_DIR$/conda/src/main/java/com/github/gtache/autosubtitle/modules/setup/conda/CondaBundledPath.java" afterDir="false" />
|
||||
<change beforePath="$PROJECT_DIR$/conda/src/main/java/com/github/gtache/autosubtitle/modules/setup/conda/CondaInstallerPath.java" beforeDir="false" afterPath="$PROJECT_DIR$/conda/src/main/java/com/github/gtache/autosubtitle/modules/setup/conda/CondaInstallerPath.java" afterDir="false" />
|
||||
<change beforePath="$PROJECT_DIR$/conda/src/main/java/com/github/gtache/autosubtitle/modules/setup/conda/CondaMinimumMajorVersion.java" beforeDir="false" afterPath="$PROJECT_DIR$/conda/src/main/java/com/github/gtache/autosubtitle/modules/setup/conda/CondaMinimumMajorVersion.java" afterDir="false" />
|
||||
<change beforePath="$PROJECT_DIR$/conda/src/main/java/com/github/gtache/autosubtitle/modules/setup/conda/CondaMinimumMinorVersion.java" beforeDir="false" afterPath="$PROJECT_DIR$/conda/src/main/java/com/github/gtache/autosubtitle/modules/setup/conda/CondaMinimumMinorVersion.java" afterDir="false" />
|
||||
<change beforePath="$PROJECT_DIR$/conda/src/main/java/com/github/gtache/autosubtitle/modules/setup/conda/CondaRootPath.java" beforeDir="false" afterPath="$PROJECT_DIR$/conda/src/main/java/com/github/gtache/autosubtitle/modules/setup/conda/CondaRootPath.java" afterDir="false" />
|
||||
<change beforePath="$PROJECT_DIR$/conda/src/main/java/com/github/gtache/autosubtitle/modules/setup/conda/CondaSystemPath.java" beforeDir="false" afterPath="$PROJECT_DIR$/conda/src/main/java/com/github/gtache/autosubtitle/modules/setup/conda/CondaSystemPath.java" afterDir="false" />
|
||||
<change beforePath="$PROJECT_DIR$/conda/src/main/java/com/github/gtache/autosubtitle/setup/conda/CondaSetupManager.java" beforeDir="false" afterPath="$PROJECT_DIR$/conda/src/main/java/com/github/gtache/autosubtitle/setup/conda/CondaSetupManager.java" afterDir="false" />
|
||||
<change beforePath="$PROJECT_DIR$/core/src/main/java/com/github/gtache/autosubtitle/archive/impl/ArchiverProviderImpl.java" beforeDir="false" afterPath="$PROJECT_DIR$/core/src/main/java/com/github/gtache/autosubtitle/archive/impl/ArchiverProviderImpl.java" afterDir="false" />
|
||||
<change beforePath="$PROJECT_DIR$/core/src/main/java/com/github/gtache/autosubtitle/archive/impl/ZipArchiver.java" beforeDir="false" afterPath="$PROJECT_DIR$/core/src/main/java/com/github/gtache/autosubtitle/archive/impl/ZipArchiver.java" afterDir="false" />
|
||||
<change beforePath="$PROJECT_DIR$/core/src/main/java/com/github/gtache/autosubtitle/modules/impl/CoreModule.java" beforeDir="false" afterPath="$PROJECT_DIR$/core/src/main/java/com/github/gtache/autosubtitle/modules/impl/CoreModule.java" afterDir="false" />
|
||||
<change beforePath="$PROJECT_DIR$/core/src/main/java/com/github/gtache/autosubtitle/modules/impl/ExecutableExtension.java" beforeDir="false" afterPath="$PROJECT_DIR$/core/src/main/java/com/github/gtache/autosubtitle/modules/impl/ExecutableExtension.java" afterDir="false" />
|
||||
<change beforePath="$PROJECT_DIR$/core/src/main/java/com/github/gtache/autosubtitle/modules/impl/FontName.java" beforeDir="false" afterPath="$PROJECT_DIR$/core/src/main/java/com/github/gtache/autosubtitle/modules/impl/FontName.java" afterDir="false" />
|
||||
<change beforePath="$PROJECT_DIR$/core/src/main/java/com/github/gtache/autosubtitle/modules/impl/FontSize.java" beforeDir="false" afterPath="$PROJECT_DIR$/core/src/main/java/com/github/gtache/autosubtitle/modules/impl/FontSize.java" afterDir="false" />
|
||||
<change beforePath="$PROJECT_DIR$/core/src/main/java/com/github/gtache/autosubtitle/modules/impl/MaxLineLength.java" beforeDir="false" afterPath="$PROJECT_DIR$/core/src/main/java/com/github/gtache/autosubtitle/modules/impl/MaxLineLength.java" afterDir="false" />
|
||||
<change beforePath="$PROJECT_DIR$/core/src/main/java/com/github/gtache/autosubtitle/modules/impl/MaxLines.java" beforeDir="false" afterPath="$PROJECT_DIR$/core/src/main/java/com/github/gtache/autosubtitle/modules/impl/MaxLines.java" afterDir="false" />
|
||||
<change beforePath="$PROJECT_DIR$/core/src/main/java/com/github/gtache/autosubtitle/modules/setup/impl/CacheRoot.java" beforeDir="false" afterPath="$PROJECT_DIR$/core/src/main/java/com/github/gtache/autosubtitle/modules/setup/impl/CacheRoot.java" afterDir="false" />
|
||||
<change beforePath="$PROJECT_DIR$/core/src/main/java/com/github/gtache/autosubtitle/modules/setup/impl/SetupModule.java" beforeDir="false" afterPath="$PROJECT_DIR$/core/src/main/java/com/github/gtache/autosubtitle/modules/setup/impl/SetupModule.java" afterDir="false" />
|
||||
<change beforePath="$PROJECT_DIR$/core/src/main/java/com/github/gtache/autosubtitle/modules/setup/impl/SubtitleExtractorSetup.java" beforeDir="false" afterPath="$PROJECT_DIR$/core/src/main/java/com/github/gtache/autosubtitle/modules/setup/impl/SubtitleExtractorSetup.java" afterDir="false" />
|
||||
<change beforePath="$PROJECT_DIR$/core/src/main/java/com/github/gtache/autosubtitle/modules/setup/impl/ToolsRoot.java" beforeDir="false" afterPath="$PROJECT_DIR$/core/src/main/java/com/github/gtache/autosubtitle/modules/setup/impl/ToolsRoot.java" afterDir="false" />
|
||||
<change beforePath="$PROJECT_DIR$/core/src/main/java/com/github/gtache/autosubtitle/modules/setup/impl/TranslatorSetup.java" beforeDir="false" afterPath="$PROJECT_DIR$/core/src/main/java/com/github/gtache/autosubtitle/modules/setup/impl/TranslatorSetup.java" afterDir="false" />
|
||||
<change beforePath="$PROJECT_DIR$/core/src/main/java/com/github/gtache/autosubtitle/modules/setup/impl/VideoConverterSetup.java" beforeDir="false" afterPath="$PROJECT_DIR$/core/src/main/java/com/github/gtache/autosubtitle/modules/setup/impl/VideoConverterSetup.java" afterDir="false" />
|
||||
<change beforePath="$PROJECT_DIR$/core/src/main/java/com/github/gtache/autosubtitle/process/impl/ProcessRunnerImpl.java" beforeDir="false" afterPath="$PROJECT_DIR$/core/src/main/java/com/github/gtache/autosubtitle/process/impl/ProcessRunnerImpl.java" afterDir="false" />
|
||||
<change beforePath="$PROJECT_DIR$/core/src/main/java/com/github/gtache/autosubtitle/subtitle/converter/impl/ASSSubtitleConverter.java" beforeDir="false" afterPath="$PROJECT_DIR$/core/src/main/java/com/github/gtache/autosubtitle/subtitle/converter/impl/ASSSubtitleConverter.java" afterDir="false" />
|
||||
<change beforePath="$PROJECT_DIR$/core/src/main/java/com/github/gtache/autosubtitle/subtitle/converter/impl/SRTSubtitleConverter.java" beforeDir="false" afterPath="$PROJECT_DIR$/core/src/main/java/com/github/gtache/autosubtitle/subtitle/converter/impl/SRTSubtitleConverter.java" afterDir="false" />
|
||||
<change beforePath="$PROJECT_DIR$/core/src/main/java/com/github/gtache/autosubtitle/subtitle/converter/impl/SubtitleConverterProviderImpl.java" beforeDir="false" afterPath="$PROJECT_DIR$/core/src/main/java/com/github/gtache/autosubtitle/subtitle/converter/impl/SubtitleConverterProviderImpl.java" afterDir="false" />
|
||||
<change beforePath="$PROJECT_DIR$/core/src/main/java/com/github/gtache/autosubtitle/subtitle/converter/json/impl/JSONSubtitleConverter.java" beforeDir="false" afterPath="$PROJECT_DIR$/core/src/main/java/com/github/gtache/autosubtitle/subtitle/converter/json/impl/JSONSubtitleConverter.java" afterDir="false" />
|
||||
<change beforePath="$PROJECT_DIR$/core/src/main/java/com/github/gtache/autosubtitle/subtitle/impl/SubtitleImporterExporterImpl.java" beforeDir="false" afterPath="$PROJECT_DIR$/core/src/main/java/com/github/gtache/autosubtitle/subtitle/impl/SubtitleImporterExporterImpl.java" afterDir="false" />
|
||||
<change beforePath="$PROJECT_DIR$/core/src/test/java/com/github/gtache/autosubtitle/modules/setup/impl/TestSetupModule.java" beforeDir="false" afterPath="$PROJECT_DIR$/core/src/test/java/com/github/gtache/autosubtitle/modules/setup/impl/TestSetupModule.java" afterDir="false" />
|
||||
<change beforePath="$PROJECT_DIR$/core/src/test/java/com/github/gtache/autosubtitle/subtitle/converter/impl/TestSRTSubtitleConverter.java" beforeDir="false" afterPath="$PROJECT_DIR$/core/src/test/java/com/github/gtache/autosubtitle/subtitle/converter/impl/TestSRTSubtitleConverter.java" afterDir="false" />
|
||||
<change beforePath="$PROJECT_DIR$/core/src/test/java/com/github/gtache/autosubtitle/subtitle/converter/json/impl/TestJSONSubtitleConverter.java" beforeDir="false" afterPath="$PROJECT_DIR$/core/src/test/java/com/github/gtache/autosubtitle/subtitle/converter/json/impl/TestJSONSubtitleConverter.java" afterDir="false" />
|
||||
<change beforePath="$PROJECT_DIR$/deepl/src/main/java/com/github/gtache/autosubtitle/modules/deepl/DeepLModule.java" beforeDir="false" afterPath="$PROJECT_DIR$/deepl/src/main/java/com/github/gtache/autosubtitle/modules/deepl/DeepLModule.java" afterDir="false" />
|
||||
<change beforePath="$PROJECT_DIR$/deepl/src/main/java/com/github/gtache/autosubtitle/setup/deepl/DeepLSetupManager.java" beforeDir="false" afterPath="$PROJECT_DIR$/deepl/src/main/java/com/github/gtache/autosubtitle/setup/deepl/DeepLSetupManager.java" afterDir="false" />
|
||||
<change beforePath="$PROJECT_DIR$/deepl/src/main/java/com/github/gtache/autosubtitle/translation/deepl/DeepLTranslator.java" beforeDir="false" afterPath="$PROJECT_DIR$/deepl/src/main/java/com/github/gtache/autosubtitle/translation/deepl/DeepLTranslator.java" afterDir="false" />
|
||||
<change beforePath="$PROJECT_DIR$/ffmpeg/src/main/java/com/github/gtache/autosubtitle/archive/ffmpeg/TarArchiver.java" beforeDir="false" afterPath="$PROJECT_DIR$/ffmpeg/src/main/java/com/github/gtache/autosubtitle/archive/ffmpeg/TarArchiver.java" afterDir="false" />
|
||||
<change beforePath="$PROJECT_DIR$/ffmpeg/src/main/java/com/github/gtache/autosubtitle/archive/ffmpeg/XZArchiver.java" beforeDir="false" afterPath="$PROJECT_DIR$/ffmpeg/src/main/java/com/github/gtache/autosubtitle/archive/ffmpeg/XZArchiver.java" afterDir="false" />
|
||||
<change beforePath="$PROJECT_DIR$/ffmpeg/src/main/java/com/github/gtache/autosubtitle/ffmpeg/FFmpegVideoConverter.java" beforeDir="false" afterPath="$PROJECT_DIR$/ffmpeg/src/main/java/com/github/gtache/autosubtitle/ffmpeg/FFmpegVideoConverter.java" afterDir="false" />
|
||||
<change beforePath="$PROJECT_DIR$/ffmpeg/src/main/java/com/github/gtache/autosubtitle/ffmpeg/FFprobeVideoLoader.java" beforeDir="false" afterPath="$PROJECT_DIR$/ffmpeg/src/main/java/com/github/gtache/autosubtitle/ffmpeg/FFprobeVideoLoader.java" afterDir="false" />
|
||||
<change beforePath="$PROJECT_DIR$/ffmpeg/src/main/java/com/github/gtache/autosubtitle/modules/ffmpeg/FFmpegModule.java" beforeDir="false" afterPath="$PROJECT_DIR$/ffmpeg/src/main/java/com/github/gtache/autosubtitle/modules/ffmpeg/FFmpegModule.java" afterDir="false" />
|
||||
<change beforePath="$PROJECT_DIR$/ffmpeg/src/main/java/com/github/gtache/autosubtitle/modules/setup/ffmpeg/FFBundledRoot.java" beforeDir="false" afterPath="$PROJECT_DIR$/ffmpeg/src/main/java/com/github/gtache/autosubtitle/modules/setup/ffmpeg/FFBundledRoot.java" afterDir="false" />
|
||||
<change beforePath="$PROJECT_DIR$/ffmpeg/src/main/java/com/github/gtache/autosubtitle/modules/setup/ffmpeg/FFProbeInstallerPath.java" beforeDir="false" afterPath="$PROJECT_DIR$/ffmpeg/src/main/java/com/github/gtache/autosubtitle/modules/setup/ffmpeg/FFProbeInstallerPath.java" afterDir="false" />
|
||||
<change beforePath="$PROJECT_DIR$/ffmpeg/src/main/java/com/github/gtache/autosubtitle/modules/setup/ffmpeg/FFmpegBundledPath.java" beforeDir="false" afterPath="$PROJECT_DIR$/ffmpeg/src/main/java/com/github/gtache/autosubtitle/modules/setup/ffmpeg/FFmpegBundledPath.java" afterDir="false" />
|
||||
<change beforePath="$PROJECT_DIR$/ffmpeg/src/main/java/com/github/gtache/autosubtitle/modules/setup/ffmpeg/FFmpegInstallerPath.java" beforeDir="false" afterPath="$PROJECT_DIR$/ffmpeg/src/main/java/com/github/gtache/autosubtitle/modules/setup/ffmpeg/FFmpegInstallerPath.java" afterDir="false" />
|
||||
<change beforePath="$PROJECT_DIR$/ffmpeg/src/main/java/com/github/gtache/autosubtitle/modules/setup/ffmpeg/FFmpegSetupModule.java" beforeDir="false" afterPath="$PROJECT_DIR$/ffmpeg/src/main/java/com/github/gtache/autosubtitle/modules/setup/ffmpeg/FFmpegSetupModule.java" afterDir="false" />
|
||||
<change beforePath="$PROJECT_DIR$/ffmpeg/src/main/java/com/github/gtache/autosubtitle/modules/setup/ffmpeg/FFmpegSystemPath.java" beforeDir="false" afterPath="$PROJECT_DIR$/ffmpeg/src/main/java/com/github/gtache/autosubtitle/modules/setup/ffmpeg/FFmpegSystemPath.java" afterDir="false" />
|
||||
<change beforePath="$PROJECT_DIR$/ffmpeg/src/main/java/com/github/gtache/autosubtitle/modules/setup/ffmpeg/FFmpegVersion.java" beforeDir="false" afterPath="$PROJECT_DIR$/ffmpeg/src/main/java/com/github/gtache/autosubtitle/modules/setup/ffmpeg/FFmpegVersion.java" afterDir="false" />
|
||||
<change beforePath="$PROJECT_DIR$/ffmpeg/src/main/java/com/github/gtache/autosubtitle/modules/setup/ffmpeg/FFprobeBundledPath.java" beforeDir="false" afterPath="$PROJECT_DIR$/ffmpeg/src/main/java/com/github/gtache/autosubtitle/modules/setup/ffmpeg/FFprobeBundledPath.java" afterDir="false" />
|
||||
<change beforePath="$PROJECT_DIR$/ffmpeg/src/main/java/com/github/gtache/autosubtitle/modules/setup/ffmpeg/FFprobeSystemPath.java" beforeDir="false" afterPath="$PROJECT_DIR$/ffmpeg/src/main/java/com/github/gtache/autosubtitle/modules/setup/ffmpeg/FFprobeSystemPath.java" afterDir="false" />
|
||||
<change beforePath="$PROJECT_DIR$/ffmpeg/src/main/java/com/github/gtache/autosubtitle/setup/ffmpeg/FFmpegSetupManager.java" beforeDir="false" afterPath="$PROJECT_DIR$/ffmpeg/src/main/java/com/github/gtache/autosubtitle/setup/ffmpeg/FFmpegSetupManager.java" afterDir="false" />
|
||||
<change beforePath="$PROJECT_DIR$/gui/api/src/main/java/com/github/gtache/autosubtitle/gui/main/MainController.java" beforeDir="false" afterPath="$PROJECT_DIR$/gui/api/src/main/java/com/github/gtache/autosubtitle/gui/MainController.java" afterDir="false" />
|
||||
<change beforePath="$PROJECT_DIR$/gui/api/src/main/java/com/github/gtache/autosubtitle/gui/main/MainModel.java" beforeDir="false" afterPath="$PROJECT_DIR$/gui/api/src/main/java/com/github/gtache/autosubtitle/gui/MainModel.java" afterDir="false" />
|
||||
<change beforePath="$PROJECT_DIR$/gui/api/src/main/java/module-info.java" beforeDir="false" afterPath="$PROJECT_DIR$/gui/api/src/main/java/module-info.java" afterDir="false" />
|
||||
<change beforePath="$PROJECT_DIR$/gui/core/src/main/java/com/github/gtache/autosubtitle/gui/impl/spi/ParametersBundleProvider.java" beforeDir="false" afterPath="$PROJECT_DIR$/gui/core/src/main/java/com/github/gtache/autosubtitle/gui/parameters/impl/spi/ParametersBundleProvider.java" afterDir="false" />
|
||||
<change beforePath="$PROJECT_DIR$/gui/core/src/main/java/com/github/gtache/autosubtitle/gui/impl/spi/ParametersBundleProviderImpl.java" beforeDir="false" afterPath="$PROJECT_DIR$/gui/core/src/main/java/com/github/gtache/autosubtitle/gui/parameters/impl/spi/ParametersBundleProviderImpl.java" afterDir="false" />
|
||||
<change beforePath="$PROJECT_DIR$/gui/core/src/main/java/com/github/gtache/autosubtitle/gui/impl/spi/SetupBundleProvider.java" beforeDir="false" afterPath="$PROJECT_DIR$/gui/core/src/main/java/com/github/gtache/autosubtitle/gui/setup/impl/spi/SetupBundleProvider.java" afterDir="false" />
|
||||
<change beforePath="$PROJECT_DIR$/gui/core/src/main/java/com/github/gtache/autosubtitle/gui/impl/spi/SetupBundleProviderImpl.java" beforeDir="false" afterPath="$PROJECT_DIR$/gui/core/src/main/java/com/github/gtache/autosubtitle/gui/setup/impl/spi/SetupBundleProviderImpl.java" afterDir="false" />
|
||||
<change beforePath="$PROJECT_DIR$/gui/core/src/main/java/com/github/gtache/autosubtitle/gui/impl/spi/SubtitlesBundleProvider.java" beforeDir="false" afterPath="$PROJECT_DIR$/gui/core/src/main/java/com/github/gtache/autosubtitle/gui/subtitles/impl/spi/SubtitlesBundleProvider.java" afterDir="false" />
|
||||
<change beforePath="$PROJECT_DIR$/gui/core/src/main/java/com/github/gtache/autosubtitle/gui/impl/spi/SubtitlesBundleProviderImpl.java" beforeDir="false" afterPath="$PROJECT_DIR$/gui/core/src/main/java/com/github/gtache/autosubtitle/gui/subtitles/impl/spi/SubtitlesBundleProviderImpl.java" afterDir="false" />
|
||||
<change beforePath="$PROJECT_DIR$/gui/core/src/main/java/com/github/gtache/autosubtitle/gui/impl/spi/WorkBundleProvider.java" beforeDir="false" afterPath="$PROJECT_DIR$/gui/core/src/main/java/com/github/gtache/autosubtitle/gui/work/impl/spi/WorkBundleProvider.java" afterDir="false" />
|
||||
<change beforePath="$PROJECT_DIR$/gui/core/src/main/java/com/github/gtache/autosubtitle/gui/impl/spi/WorkBundleProviderImpl.java" beforeDir="false" afterPath="$PROJECT_DIR$/gui/core/src/main/java/com/github/gtache/autosubtitle/gui/work/impl/spi/WorkBundleProviderImpl.java" afterDir="false" />
|
||||
<change beforePath="$PROJECT_DIR$/gui/core/src/main/java/com/github/gtache/autosubtitle/modules/gui/impl/GuiCoreModule.java" beforeDir="false" afterPath="$PROJECT_DIR$/gui/core/src/main/java/com/github/gtache/autosubtitle/modules/gui/impl/GuiCoreModule.java" afterDir="false" />
|
||||
<change beforePath="$PROJECT_DIR$/gui/core/src/main/java/com/github/gtache/autosubtitle/modules/gui/impl/Pause.java" beforeDir="false" afterPath="$PROJECT_DIR$/gui/core/src/main/java/com/github/gtache/autosubtitle/modules/gui/impl/Pause.java" afterDir="false" />
|
||||
<change beforePath="$PROJECT_DIR$/gui/core/src/main/java/com/github/gtache/autosubtitle/modules/gui/impl/Play.java" beforeDir="false" afterPath="$PROJECT_DIR$/gui/core/src/main/java/com/github/gtache/autosubtitle/modules/gui/impl/Play.java" afterDir="false" />
|
||||
<change beforePath="$PROJECT_DIR$/gui/core/src/main/java/module-info.java" beforeDir="false" afterPath="$PROJECT_DIR$/gui/core/src/main/java/module-info.java" afterDir="false" />
|
||||
<change beforePath="$PROJECT_DIR$/gui/core/src/main/resources/com/github/gtache/autosubtitle/gui/impl/MediaBundle.properties" beforeDir="false" afterPath="$PROJECT_DIR$/gui/core/src/main/resources/com/github/gtache/autosubtitle/gui/media/impl/MediaBundle.properties" afterDir="false" />
|
||||
<change beforePath="$PROJECT_DIR$/gui/core/src/main/resources/com/github/gtache/autosubtitle/gui/impl/MediaBundle_fr.properties" beforeDir="false" afterPath="$PROJECT_DIR$/gui/core/src/main/resources/com/github/gtache/autosubtitle/gui/media/impl/MediaBundle_fr.properties" afterDir="false" />
|
||||
<change beforePath="$PROJECT_DIR$/gui/core/src/main/resources/com/github/gtache/autosubtitle/gui/impl/ParametersBundle.properties" beforeDir="false" afterPath="$PROJECT_DIR$/gui/core/src/main/resources/com/github/gtache/autosubtitle/gui/parameters/impl/ParametersBundle.properties" afterDir="false" />
|
||||
<change beforePath="$PROJECT_DIR$/gui/core/src/main/resources/com/github/gtache/autosubtitle/gui/impl/ParametersBundle_fr.properties" beforeDir="false" afterPath="$PROJECT_DIR$/gui/core/src/main/resources/com/github/gtache/autosubtitle/gui/parameters/impl/ParametersBundle_fr.properties" afterDir="false" />
|
||||
<change beforePath="$PROJECT_DIR$/gui/core/src/main/resources/com/github/gtache/autosubtitle/gui/impl/SetupBundle.properties" beforeDir="false" afterPath="$PROJECT_DIR$/gui/core/src/main/resources/com/github/gtache/autosubtitle/gui/setup/impl/SetupBundle.properties" afterDir="false" />
|
||||
<change beforePath="$PROJECT_DIR$/gui/core/src/main/resources/com/github/gtache/autosubtitle/gui/impl/SetupBundle_fr.properties" beforeDir="false" afterPath="$PROJECT_DIR$/gui/core/src/main/resources/com/github/gtache/autosubtitle/gui/setup/impl/SetupBundle_fr.properties" afterDir="false" />
|
||||
<change beforePath="$PROJECT_DIR$/gui/core/src/main/resources/com/github/gtache/autosubtitle/gui/impl/SubtitlesBundle.properties" beforeDir="false" afterPath="$PROJECT_DIR$/gui/core/src/main/resources/com/github/gtache/autosubtitle/gui/subtitles/impl/SubtitlesBundle.properties" afterDir="false" />
|
||||
<change beforePath="$PROJECT_DIR$/gui/core/src/main/resources/com/github/gtache/autosubtitle/gui/impl/SubtitlesBundle_fr.properties" beforeDir="false" afterPath="$PROJECT_DIR$/gui/core/src/main/resources/com/github/gtache/autosubtitle/gui/subtitles/impl/SubtitlesBundle_fr.properties" afterDir="false" />
|
||||
<change beforePath="$PROJECT_DIR$/gui/core/src/main/resources/com/github/gtache/autosubtitle/gui/impl/WorkBundle.properties" beforeDir="false" afterPath="$PROJECT_DIR$/gui/core/src/main/resources/com/github/gtache/autosubtitle/gui/work/impl/WorkBundle.properties" afterDir="false" />
|
||||
<change beforePath="$PROJECT_DIR$/gui/core/src/main/resources/com/github/gtache/autosubtitle/gui/impl/WorkBundle_fr.properties" beforeDir="false" afterPath="$PROJECT_DIR$/gui/core/src/main/resources/com/github/gtache/autosubtitle/gui/work/impl/WorkBundle_fr.properties" afterDir="false" />
|
||||
<change beforePath="$PROJECT_DIR$/gui/core/src/main/resources/com/github/gtache/autosubtitle/gui/impl/pause_64.png" beforeDir="false" afterPath="$PROJECT_DIR$/gui/core/src/main/resources/com/github/gtache/autosubtitle/gui/media/impl/pause_64.png" afterDir="false" />
|
||||
<change beforePath="$PROJECT_DIR$/gui/core/src/main/resources/com/github/gtache/autosubtitle/gui/impl/play_64.png" beforeDir="false" afterPath="$PROJECT_DIR$/gui/core/src/main/resources/com/github/gtache/autosubtitle/gui/media/impl/play_64.png" afterDir="false" />
|
||||
<change beforePath="$PROJECT_DIR$/gui/fx/src/main/java/com/github/gtache/autosubtitle/gui/main/fx/FXMainController.java" beforeDir="false" afterPath="$PROJECT_DIR$/gui/fx/src/main/java/com/github/gtache/autosubtitle/gui/fx/FXMainController.java" afterDir="false" />
|
||||
<change beforePath="$PROJECT_DIR$/gui/fx/src/main/java/com/github/gtache/autosubtitle/gui/main/fx/FXMainModel.java" beforeDir="false" afterPath="$PROJECT_DIR$/gui/fx/src/main/java/com/github/gtache/autosubtitle/gui/fx/FXMainModel.java" afterDir="false" />
|
||||
<change beforePath="$PROJECT_DIR$/gui/fx/src/main/java/com/github/gtache/autosubtitle/gui/media/fx/FXMediaBinder.java" beforeDir="false" afterPath="$PROJECT_DIR$/gui/fx/src/main/java/com/github/gtache/autosubtitle/gui/media/fx/FXMediaBinder.java" afterDir="false" />
|
||||
<change beforePath="$PROJECT_DIR$/gui/fx/src/main/java/com/github/gtache/autosubtitle/gui/media/fx/FXMediaController.java" beforeDir="false" afterPath="$PROJECT_DIR$/gui/fx/src/main/java/com/github/gtache/autosubtitle/gui/media/fx/FXMediaController.java" afterDir="false" />
|
||||
<change beforePath="$PROJECT_DIR$/gui/fx/src/main/java/com/github/gtache/autosubtitle/gui/media/fx/FXMediaModel.java" beforeDir="false" afterPath="$PROJECT_DIR$/gui/fx/src/main/java/com/github/gtache/autosubtitle/gui/media/fx/FXMediaModel.java" afterDir="false" />
|
||||
<change beforePath="$PROJECT_DIR$/gui/fx/src/main/java/com/github/gtache/autosubtitle/gui/parameters/fx/FXParametersController.java" beforeDir="false" afterPath="$PROJECT_DIR$/gui/fx/src/main/java/com/github/gtache/autosubtitle/gui/parameters/fx/FXParametersController.java" afterDir="false" />
|
||||
<change beforePath="$PROJECT_DIR$/core/src/test/java/com/github/gtache/autosubtitle/subtitle/converter/impl/TestASSSubtitleConverter.java" beforeDir="false" afterPath="$PROJECT_DIR$/core/src/test/java/com/github/gtache/autosubtitle/subtitle/converter/impl/TestASSSubtitleConverter.java" afterDir="false" />
|
||||
<change beforePath="$PROJECT_DIR$/gui/fx/src/main/java/com/github/gtache/autosubtitle/gui/parameters/fx/FXParametersModel.java" beforeDir="false" afterPath="$PROJECT_DIR$/gui/fx/src/main/java/com/github/gtache/autosubtitle/gui/parameters/fx/FXParametersModel.java" afterDir="false" />
|
||||
<change beforePath="$PROJECT_DIR$/gui/fx/src/main/java/com/github/gtache/autosubtitle/gui/setup/fx/FXSetupModel.java" beforeDir="false" afterPath="$PROJECT_DIR$/gui/fx/src/main/java/com/github/gtache/autosubtitle/gui/setup/fx/FXSetupModel.java" afterDir="false" />
|
||||
<change beforePath="$PROJECT_DIR$/gui/fx/src/main/java/com/github/gtache/autosubtitle/gui/subtitles/fx/FXSubtitlesBinder.java" beforeDir="false" afterPath="$PROJECT_DIR$/gui/fx/src/main/java/com/github/gtache/autosubtitle/gui/subtitles/fx/FXSubtitlesBinder.java" afterDir="false" />
|
||||
<change beforePath="$PROJECT_DIR$/gui/fx/src/main/java/com/github/gtache/autosubtitle/gui/subtitles/fx/FXSubtitlesController.java" beforeDir="false" afterPath="$PROJECT_DIR$/gui/fx/src/main/java/com/github/gtache/autosubtitle/gui/subtitles/fx/FXSubtitlesController.java" afterDir="false" />
|
||||
<change beforePath="$PROJECT_DIR$/gui/fx/src/main/java/com/github/gtache/autosubtitle/gui/subtitles/fx/FXSubtitlesModel.java" beforeDir="false" afterPath="$PROJECT_DIR$/gui/fx/src/main/java/com/github/gtache/autosubtitle/gui/subtitles/fx/FXSubtitlesModel.java" afterDir="false" />
|
||||
<change beforePath="$PROJECT_DIR$/gui/fx/src/main/java/com/github/gtache/autosubtitle/gui/work/fx/FXWorkBinder.java" beforeDir="false" afterPath="$PROJECT_DIR$/gui/fx/src/main/java/com/github/gtache/autosubtitle/gui/work/fx/FXWorkBinder.java" afterDir="false" />
|
||||
<change beforePath="$PROJECT_DIR$/gui/fx/src/main/java/com/github/gtache/autosubtitle/gui/work/fx/FXWorkController.java" beforeDir="false" afterPath="$PROJECT_DIR$/gui/fx/src/main/java/com/github/gtache/autosubtitle/gui/work/fx/FXWorkController.java" afterDir="false" />
|
||||
<change beforePath="$PROJECT_DIR$/gui/fx/src/main/java/com/github/gtache/autosubtitle/gui/work/fx/FXWorkModel.java" beforeDir="false" afterPath="$PROJECT_DIR$/gui/fx/src/main/java/com/github/gtache/autosubtitle/gui/work/fx/FXWorkModel.java" afterDir="false" />
|
||||
<change beforePath="$PROJECT_DIR$/gui/fx/src/main/java/com/github/gtache/autosubtitle/modules/gui/fx/FXModule.java" beforeDir="false" afterPath="$PROJECT_DIR$/gui/fx/src/main/java/com/github/gtache/autosubtitle/modules/gui/fx/FXModule.java" afterDir="false" />
|
||||
<change beforePath="$PROJECT_DIR$/gui/fx/src/main/java/com/github/gtache/autosubtitle/setup/gui/fx/FXSetupUserBridge.java" beforeDir="false" afterPath="$PROJECT_DIR$/gui/fx/src/main/java/com/github/gtache/autosubtitle/setup/gui/fx/FXSetupUserBridge.java" afterDir="false" />
|
||||
<change beforePath="$PROJECT_DIR$/gui/fx/src/main/java/module-info.java" beforeDir="false" afterPath="$PROJECT_DIR$/gui/fx/src/main/java/module-info.java" afterDir="false" />
|
||||
<change beforePath="$PROJECT_DIR$/gui/fx/src/main/resources/com/github/gtache/autosubtitle/gui/fx/mainView.fxml" beforeDir="false" afterPath="$PROJECT_DIR$/gui/fx/src/main/resources/com/github/gtache/autosubtitle/gui/fx/mainView.fxml" afterDir="false" />
|
||||
<change beforePath="$PROJECT_DIR$/gui/fx/src/main/resources/com/github/gtache/autosubtitle/gui/fx/mediaView.fxml" beforeDir="false" afterPath="$PROJECT_DIR$/gui/fx/src/main/resources/com/github/gtache/autosubtitle/gui/media/fx/mediaView.fxml" afterDir="false" />
|
||||
<change beforePath="$PROJECT_DIR$/gui/fx/src/main/resources/com/github/gtache/autosubtitle/gui/fx/parametersView.fxml" beforeDir="false" afterPath="$PROJECT_DIR$/gui/fx/src/main/resources/com/github/gtache/autosubtitle/gui/parameters/fx/parametersView.fxml" afterDir="false" />
|
||||
<change beforePath="$PROJECT_DIR$/gui/fx/src/main/resources/com/github/gtache/autosubtitle/gui/fx/setupView.fxml" beforeDir="false" afterPath="$PROJECT_DIR$/gui/fx/src/main/resources/com/github/gtache/autosubtitle/gui/setup/fx/setupView.fxml" afterDir="false" />
|
||||
<change beforePath="$PROJECT_DIR$/gui/fx/src/main/resources/com/github/gtache/autosubtitle/gui/fx/subtitlesView.fxml" beforeDir="false" afterPath="$PROJECT_DIR$/gui/fx/src/main/resources/com/github/gtache/autosubtitle/gui/subtitles/fx/subtitlesView.fxml" afterDir="false" />
|
||||
<change beforePath="$PROJECT_DIR$/gui/fx/src/main/resources/com/github/gtache/autosubtitle/gui/fx/workView.fxml" beforeDir="false" afterPath="$PROJECT_DIR$/gui/fx/src/main/resources/com/github/gtache/autosubtitle/gui/work/fx/workView.fxml" afterDir="false" />
|
||||
<change beforePath="$PROJECT_DIR$/gui/fx/src/test/java/com/github/gtache/autosubtitle/gui/main/fx/TestFXMainController.java" beforeDir="false" afterPath="$PROJECT_DIR$/gui/fx/src/test/java/com/github/gtache/autosubtitle/gui/fx/TestFXMainController.java" afterDir="false" />
|
||||
<change beforePath="$PROJECT_DIR$/gui/fx/src/test/java/com/github/gtache/autosubtitle/gui/main/fx/TestFXMainModel.java" beforeDir="false" afterPath="$PROJECT_DIR$/gui/fx/src/test/java/com/github/gtache/autosubtitle/gui/fx/TestFXMainModel.java" afterDir="false" />
|
||||
<change beforePath="$PROJECT_DIR$/gui/fx/src/test/java/com/github/gtache/autosubtitle/gui/subtitles/fx/TestFXSubtitlesBinder.java" beforeDir="false" afterPath="$PROJECT_DIR$/gui/fx/src/test/java/com/github/gtache/autosubtitle/gui/subtitles/fx/TestFXSubtitlesBinder.java" afterDir="false" />
|
||||
<change beforePath="$PROJECT_DIR$/gui/fx/src/test/java/com/github/gtache/autosubtitle/gui/subtitles/fx/TestFXSubtitlesController.java" beforeDir="false" afterPath="$PROJECT_DIR$/gui/fx/src/test/java/com/github/gtache/autosubtitle/gui/subtitles/fx/TestFXSubtitlesController.java" afterDir="false" />
|
||||
<change beforePath="$PROJECT_DIR$/gui/fx/src/test/java/com/github/gtache/autosubtitle/gui/subtitles/fx/TestFXSubtitlesModel.java" beforeDir="false" afterPath="$PROJECT_DIR$/gui/fx/src/test/java/com/github/gtache/autosubtitle/gui/subtitles/fx/TestFXSubtitlesModel.java" afterDir="false" />
|
||||
<change beforePath="$PROJECT_DIR$/gui/fx/src/test/java/com/github/gtache/autosubtitle/gui/work/fx/TestFXWorkBinder.java" beforeDir="false" afterPath="$PROJECT_DIR$/gui/fx/src/test/java/com/github/gtache/autosubtitle/gui/work/fx/TestFXWorkBinder.java" afterDir="false" />
|
||||
<change beforePath="$PROJECT_DIR$/gui/fx/src/test/java/com/github/gtache/autosubtitle/gui/work/fx/TestFXWorkController.java" beforeDir="false" afterPath="$PROJECT_DIR$/gui/fx/src/test/java/com/github/gtache/autosubtitle/gui/work/fx/TestFXWorkController.java" afterDir="false" />
|
||||
<change beforePath="$PROJECT_DIR$/gui/fx/src/test/java/com/github/gtache/autosubtitle/gui/work/fx/TestFXWorkModel.java" beforeDir="false" afterPath="$PROJECT_DIR$/gui/fx/src/test/java/com/github/gtache/autosubtitle/gui/work/fx/TestFXWorkModel.java" afterDir="false" />
|
||||
<change beforePath="$PROJECT_DIR$/gui/fx/src/test/java/com/github/gtache/autosubtitle/modules/gui/fx/TestFXModule.java" beforeDir="false" afterPath="$PROJECT_DIR$/gui/fx/src/test/java/com/github/gtache/autosubtitle/modules/gui/fx/TestFXModule.java" afterDir="false" />
|
||||
<change beforePath="$PROJECT_DIR$/gui/fx/src/test/java/com/github/gtache/autosubtitle/setup/gui/fx/TestFXSetupUserBridge.java" beforeDir="false" afterPath="$PROJECT_DIR$/gui/fx/src/test/java/com/github/gtache/autosubtitle/setup/gui/fx/TestFXSetupUserBridge.java" afterDir="false" />
|
||||
<change beforePath="$PROJECT_DIR$/gui/run/src/main/java/com/github/gtache/autosubtitle/modules/gui/run/RunComponent.java" beforeDir="false" afterPath="$PROJECT_DIR$/gui/run/src/main/java/com/github/gtache/autosubtitle/modules/gui/run/RunComponent.java" afterDir="false" />
|
||||
<change beforePath="$PROJECT_DIR$/whisper/base/src/main/java/com/github/gtache/autosubtitle/modules/setup/whisper/base/Whisper.java" beforeDir="false" afterPath="$PROJECT_DIR$/whisper/base/src/main/java/com/github/gtache/autosubtitle/modules/setup/whisper/base/Whisper.java" afterDir="false" />
|
||||
<change beforePath="$PROJECT_DIR$/whisper/base/src/main/java/com/github/gtache/autosubtitle/modules/setup/whisper/base/WhisperBundledRoot.java" beforeDir="false" afterPath="$PROJECT_DIR$/whisper/base/src/main/java/com/github/gtache/autosubtitle/modules/setup/whisper/base/WhisperBundledRoot.java" afterDir="false" />
|
||||
<change beforePath="$PROJECT_DIR$/whisper/base/src/main/java/com/github/gtache/autosubtitle/modules/setup/whisper/base/WhisperPythonVersion.java" beforeDir="false" afterPath="$PROJECT_DIR$/whisper/base/src/main/java/com/github/gtache/autosubtitle/modules/setup/whisper/base/WhisperPythonVersion.java" afterDir="false" />
|
||||
<change beforePath="$PROJECT_DIR$/whisper/base/src/main/java/com/github/gtache/autosubtitle/modules/setup/whisper/base/WhisperVenvPath.java" beforeDir="false" afterPath="$PROJECT_DIR$/whisper/base/src/main/java/com/github/gtache/autosubtitle/modules/setup/whisper/base/WhisperVenvPath.java" afterDir="false" />
|
||||
<change beforePath="$PROJECT_DIR$/whisper/base/src/main/java/com/github/gtache/autosubtitle/setup/whisper/base/WhisperSetupManager.java" beforeDir="false" afterPath="$PROJECT_DIR$/whisper/base/src/main/java/com/github/gtache/autosubtitle/setup/whisper/base/WhisperSetupManager.java" afterDir="false" />
|
||||
<change beforePath="$PROJECT_DIR$/whisper/base/src/main/java/com/github/gtache/autosubtitle/subtitle/converter/json/whisper/base/JSONSubtitleConverter.java" beforeDir="false" afterPath="$PROJECT_DIR$/whisper/base/src/main/java/com/github/gtache/autosubtitle/subtitle/converter/json/whisper/base/JSONSubtitleConverter.java" afterDir="false" />
|
||||
<change beforePath="$PROJECT_DIR$/whisper/base/src/main/java/com/github/gtache/autosubtitle/subtitle/extractor/whisper/base/WhisperSubtitleExtractor.java" beforeDir="false" afterPath="$PROJECT_DIR$/whisper/base/src/main/java/com/github/gtache/autosubtitle/subtitle/extractor/whisper/base/WhisperSubtitleExtractor.java" afterDir="false" />
|
||||
<change beforePath="$PROJECT_DIR$/whisper/base/src/main/java/com/github/gtache/autosubtitle/whisper/base/WhisperExtractionModelProvider.java" beforeDir="false" afterPath="$PROJECT_DIR$/whisper/base/src/main/java/com/github/gtache/autosubtitle/whisper/base/WhisperExtractionModelProvider.java" afterDir="false" />
|
||||
<change beforePath="$PROJECT_DIR$/whisper/whisperx/src/main/java/com/github/gtache/autosubtitle/modules/setup/whisperx/WhisperX.java" beforeDir="false" afterPath="$PROJECT_DIR$/whisper/whisperx/src/main/java/com/github/gtache/autosubtitle/modules/setup/whisperx/WhisperX.java" afterDir="false" />
|
||||
<change beforePath="$PROJECT_DIR$/whisper/whisperx/src/main/java/com/github/gtache/autosubtitle/modules/setup/whisperx/WhisperXBundledRoot.java" beforeDir="false" afterPath="$PROJECT_DIR$/whisper/whisperx/src/main/java/com/github/gtache/autosubtitle/modules/setup/whisperx/WhisperXBundledRoot.java" afterDir="false" />
|
||||
<change beforePath="$PROJECT_DIR$/whisper/whisperx/src/main/java/com/github/gtache/autosubtitle/modules/setup/whisperx/WhisperXPythonVersion.java" beforeDir="false" afterPath="$PROJECT_DIR$/whisper/whisperx/src/main/java/com/github/gtache/autosubtitle/modules/setup/whisperx/WhisperXPythonVersion.java" afterDir="false" />
|
||||
<change beforePath="$PROJECT_DIR$/whisper/whisperx/src/main/java/com/github/gtache/autosubtitle/modules/setup/whisperx/WhisperXSetupModule.java" beforeDir="false" afterPath="$PROJECT_DIR$/whisper/whisperx/src/main/java/com/github/gtache/autosubtitle/modules/setup/whisperx/WhisperXSetupModule.java" afterDir="false" />
|
||||
<change beforePath="$PROJECT_DIR$/whisper/whisperx/src/main/java/com/github/gtache/autosubtitle/modules/setup/whisperx/WhisperXVenvPath.java" beforeDir="false" afterPath="$PROJECT_DIR$/whisper/whisperx/src/main/java/com/github/gtache/autosubtitle/modules/setup/whisperx/WhisperXVenvPath.java" afterDir="false" />
|
||||
<change beforePath="$PROJECT_DIR$/whisper/whisperx/src/main/java/com/github/gtache/autosubtitle/modules/whisperx/WhisperXModule.java" beforeDir="false" afterPath="$PROJECT_DIR$/whisper/whisperx/src/main/java/com/github/gtache/autosubtitle/modules/whisperx/WhisperXModule.java" afterDir="false" />
|
||||
<change beforePath="$PROJECT_DIR$/whisper/whisperx/src/main/java/com/github/gtache/autosubtitle/setup/whisperx/WhisperXSetupManager.java" beforeDir="false" afterPath="$PROJECT_DIR$/whisper/whisperx/src/main/java/com/github/gtache/autosubtitle/setup/whisperx/WhisperXSetupManager.java" afterDir="false" />
|
||||
<change beforePath="$PROJECT_DIR$/whisper/whisperx/src/main/java/com/github/gtache/autosubtitle/subtitle/converter/json/whisperx/WhisperXJSONSubtitleConverter.java" beforeDir="false" afterPath="$PROJECT_DIR$/whisper/whisperx/src/main/java/com/github/gtache/autosubtitle/subtitle/converter/json/whisperx/WhisperXJSONSubtitleConverter.java" afterDir="false" />
|
||||
<change beforePath="$PROJECT_DIR$/whisper/whisperx/src/main/java/com/github/gtache/autosubtitle/subtitle/extractor/whisperx/WhisperXSubtitleExtractor.java" beforeDir="false" afterPath="$PROJECT_DIR$/whisper/whisperx/src/main/java/com/github/gtache/autosubtitle/subtitle/extractor/whisperx/WhisperXSubtitleExtractor.java" afterDir="false" />
|
||||
<change beforePath="$PROJECT_DIR$/whisper/whisperx/src/main/java/com/github/gtache/autosubtitle/whisperx/WhisperXExtractionModelProvider.java" beforeDir="false" afterPath="$PROJECT_DIR$/whisper/whisperx/src/main/java/com/github/gtache/autosubtitle/whisperx/WhisperXExtractionModelProvider.java" afterDir="false" />
|
||||
<change beforePath="$PROJECT_DIR$/gui/fx/src/main/resources/com/github/gtache/autosubtitle/gui/setup/fx/setupView.fxml" beforeDir="false" afterPath="$PROJECT_DIR$/gui/fx/src/main/resources/com/github/gtache/autosubtitle/gui/setup/fx/setupView.fxml" afterDir="false" />
|
||||
</list>
|
||||
<option name="SHOW_DIALOG" value="false" />
|
||||
<option name="HIGHLIGHT_CONFLICTS" value="true" />
|
||||
@@ -192,6 +65,9 @@
|
||||
"keyToString": {
|
||||
"Application.Main.executor": "Run",
|
||||
"JUnit.All in autosubtitle-core.executor": "Run",
|
||||
"JUnit.TestASSSubtitleConverter.executor": "Coverage",
|
||||
"JUnit.TestASSSubtitleConverter.testFormatDefaultFont.executor": "Run",
|
||||
"JUnit.TestASSSubtitleConverter.testParseFormat.executor": "Debug",
|
||||
"Maven.autosubtitle [clean,package,-DskipTests].executor": "Run",
|
||||
"Maven.autosubtitle [clean,package].executor": "Run",
|
||||
"Maven.autosubtitle [clean].executor": "Run",
|
||||
@@ -240,7 +116,7 @@
|
||||
<command value="mvn clean package -DskipTests" />
|
||||
</option>
|
||||
</component>
|
||||
<component name="RunManager" selected="Application.Main">
|
||||
<component name="RunManager" selected="JUnit.TestASSSubtitleConverter">
|
||||
<configuration default="true" type="Applet">
|
||||
<option name="POLICY_FILE" value="$APPLICATION_HOME_DIR$/bin/appletviewer.policy" />
|
||||
<method v="2">
|
||||
@@ -285,6 +161,56 @@
|
||||
<option name="Make" enabled="true" />
|
||||
</method>
|
||||
</configuration>
|
||||
<configuration name="TestASSSubtitleConverter" type="JUnit" factoryName="JUnit" temporary="true" nameIsGenerated="true">
|
||||
<module name="autosubtitle-core" />
|
||||
<extension name="coverage">
|
||||
<pattern>
|
||||
<option name="PATTERN" value="com.github.gtache.autosubtitle.subtitle.converter.impl.*" />
|
||||
<option name="ENABLED" value="true" />
|
||||
</pattern>
|
||||
</extension>
|
||||
<option name="PACKAGE_NAME" value="com.github.gtache.autosubtitle.subtitle.converter.impl" />
|
||||
<option name="MAIN_CLASS_NAME" value="com.github.gtache.autosubtitle.subtitle.converter.impl.TestASSSubtitleConverter" />
|
||||
<option name="TEST_OBJECT" value="class" />
|
||||
<option name="WORKING_DIRECTORY" value="%MODULE_WORKING_DIR%" />
|
||||
<method v="2">
|
||||
<option name="Make" enabled="true" />
|
||||
</method>
|
||||
</configuration>
|
||||
<configuration name="TestASSSubtitleConverter.testFormatDefaultFont" type="JUnit" factoryName="JUnit" temporary="true" nameIsGenerated="true">
|
||||
<module name="autosubtitle-core" />
|
||||
<extension name="coverage">
|
||||
<pattern>
|
||||
<option name="PATTERN" value="com.github.gtache.autosubtitle.subtitle.converter.impl.*" />
|
||||
<option name="ENABLED" value="true" />
|
||||
</pattern>
|
||||
</extension>
|
||||
<option name="PACKAGE_NAME" value="com.github.gtache.autosubtitle.subtitle.converter.impl" />
|
||||
<option name="MAIN_CLASS_NAME" value="com.github.gtache.autosubtitle.subtitle.converter.impl.TestASSSubtitleConverter" />
|
||||
<option name="METHOD_NAME" value="testFormatDefaultFont" />
|
||||
<option name="TEST_OBJECT" value="method" />
|
||||
<option name="WORKING_DIRECTORY" value="%MODULE_WORKING_DIR%" />
|
||||
<method v="2">
|
||||
<option name="Make" enabled="true" />
|
||||
</method>
|
||||
</configuration>
|
||||
<configuration name="TestASSSubtitleConverter.testParseFormat" type="JUnit" factoryName="JUnit" temporary="true" nameIsGenerated="true">
|
||||
<module name="autosubtitle-core" />
|
||||
<extension name="coverage">
|
||||
<pattern>
|
||||
<option name="PATTERN" value="com.github.gtache.autosubtitle.subtitle.converter.impl.*" />
|
||||
<option name="ENABLED" value="true" />
|
||||
</pattern>
|
||||
</extension>
|
||||
<option name="PACKAGE_NAME" value="com.github.gtache.autosubtitle.subtitle.converter.impl" />
|
||||
<option name="MAIN_CLASS_NAME" value="com.github.gtache.autosubtitle.subtitle.converter.impl.TestASSSubtitleConverter" />
|
||||
<option name="METHOD_NAME" value="testParseFormat" />
|
||||
<option name="TEST_OBJECT" value="method" />
|
||||
<option name="WORKING_DIRECTORY" value="%MODULE_WORKING_DIR%" />
|
||||
<method v="2">
|
||||
<option name="Make" enabled="true" />
|
||||
</method>
|
||||
</configuration>
|
||||
<configuration default="true" type="JUnit" factoryName="JUnit">
|
||||
<option name="TEST_OBJECT" value="class" />
|
||||
<option name="WORKING_DIRECTORY" value="%MODULE_WORKING_DIR%" />
|
||||
@@ -366,6 +292,9 @@
|
||||
</configuration>
|
||||
<recent_temporary>
|
||||
<list>
|
||||
<item itemvalue="JUnit.TestASSSubtitleConverter" />
|
||||
<item itemvalue="JUnit.TestASSSubtitleConverter.testFormatDefaultFont" />
|
||||
<item itemvalue="JUnit.TestASSSubtitleConverter.testParseFormat" />
|
||||
<item itemvalue="Application.Main" />
|
||||
<item itemvalue="JUnit.All in autosubtitle-core" />
|
||||
</list>
|
||||
@@ -389,7 +318,10 @@
|
||||
<updated>1727983986841</updated>
|
||||
<workItem from="1727983987865" duration="45000" />
|
||||
<workItem from="1727984039387" duration="1480000" />
|
||||
<workItem from="1728066754302" duration="4517000" />
|
||||
<workItem from="1728066754302" duration="4620000" />
|
||||
<workItem from="1728153813144" duration="6710000" />
|
||||
<workItem from="1728207088557" duration="675000" />
|
||||
<workItem from="1728227281845" duration="2280000" />
|
||||
</task>
|
||||
<servers />
|
||||
</component>
|
||||
@@ -397,6 +329,9 @@
|
||||
<option name="version" value="3" />
|
||||
</component>
|
||||
<component name="com.intellij.coverage.CoverageDataManagerImpl">
|
||||
<SUITE FILE_PATH="coverage/auto_subtitle$TestASSSubtitleConverter.ic" NAME="TestASSSubtitleConverter Coverage Results" MODIFIED="1728229568706" SOURCE_PROVIDER="com.intellij.coverage.DefaultCoverageFileProvider" RUNNER="idea" COVERAGE_BY_TEST_ENABLED="false" COVERAGE_TRACING_ENABLED="true">
|
||||
<FILTER>com.github.gtache.autosubtitle.subtitle.converter.impl.*</FILTER>
|
||||
</SUITE>
|
||||
<SUITE FILE_PATH="coverage/auto_subtitle$All_in_autosubtitle_core.ic" NAME="All in autosubtitle-core Coverage Results" MODIFIED="1728070687799" SOURCE_PROVIDER="com.intellij.coverage.DefaultCoverageFileProvider" RUNNER="idea" COVERAGE_BY_TEST_ENABLED="false" COVERAGE_TRACING_ENABLED="true" />
|
||||
</component>
|
||||
</project>
|
||||
@@ -1,6 +1,7 @@
|
||||
package com.github.gtache.autosubtitle.subtitle.converter.impl;
|
||||
|
||||
import com.github.gtache.autosubtitle.VideoInfo;
|
||||
import com.github.gtache.autosubtitle.subtitle.Bounds;
|
||||
import com.github.gtache.autosubtitle.subtitle.Font;
|
||||
import com.github.gtache.autosubtitle.subtitle.Subtitle;
|
||||
import com.github.gtache.autosubtitle.subtitle.SubtitleCollection;
|
||||
@@ -8,19 +9,21 @@ import com.github.gtache.autosubtitle.subtitle.converter.FormatOptions;
|
||||
import com.github.gtache.autosubtitle.subtitle.converter.ParseException;
|
||||
import com.github.gtache.autosubtitle.subtitle.converter.ParseOptions;
|
||||
import com.github.gtache.autosubtitle.subtitle.converter.SubtitleConverter;
|
||||
import com.github.gtache.autosubtitle.subtitle.impl.BoundsImpl;
|
||||
import com.github.gtache.autosubtitle.subtitle.impl.FontImpl;
|
||||
import com.github.gtache.autosubtitle.subtitle.impl.SubtitleCollectionImpl;
|
||||
import com.github.gtache.autosubtitle.subtitle.impl.SubtitleImpl;
|
||||
import com.github.gtache.autosubtitle.translation.Translator;
|
||||
|
||||
import javax.inject.Inject;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.Arrays;
|
||||
import java.util.Collection;
|
||||
import java.util.Comparator;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.Objects;
|
||||
import java.util.Set;
|
||||
import java.util.regex.Pattern;
|
||||
import java.util.stream.Collectors;
|
||||
|
||||
@@ -34,7 +37,30 @@ public class ASSSubtitleConverter implements SubtitleConverter<SubtitleImpl> {
|
||||
private static final String DIALOGUE = "Dialogue:";
|
||||
private static final String EVENTS_SECTION = "[Events]";
|
||||
private static final String STYLES_SECTION = "[V4+ Styles]";
|
||||
private static final String START_FIELD = "Start";
|
||||
private static final String END_FIELD = "End";
|
||||
private static final String STYLE_FIELD = "Style";
|
||||
private static final String TEXT_FIELD = "Text";
|
||||
private static final String NAME_FIELD = "Name";
|
||||
private static final String FONTNAME_FIELD = "Fontname";
|
||||
private static final String FONTSIZE_FIELD = "Fontsize";
|
||||
private static final String MARGIN_L_FIELD = "MarginL";
|
||||
private static final String MARGIN_R_FIELD = "MarginR";
|
||||
private static final String MARGIN_V_FIELD = "MarginV";
|
||||
private static final List<String> STYLE_FIELDS = List.of(NAME_FIELD, FONTNAME_FIELD, FONTSIZE_FIELD, "PrimaryColour",
|
||||
"SecondaryColour", "OutlineColour", "BackColour", "Bold", "Italic",
|
||||
"Underline", "StrikeOut", "ScaleX", "ScaleY", "Spacing", "Angle", "BorderStyle", "Outline", "Shadow", "Alignment",
|
||||
MARGIN_L_FIELD, MARGIN_R_FIELD, MARGIN_V_FIELD, "AlphaLevel", "Encoding");
|
||||
private static final Set<String> REQUIRED_STYLE_FIELDS = Set.of(NAME_FIELD, FONTNAME_FIELD, FONTSIZE_FIELD);
|
||||
private static final List<String> EVENT_FIELDS = List.of("Layer", START_FIELD, END_FIELD, STYLE_FIELD, "Name", MARGIN_L_FIELD, MARGIN_R_FIELD, MARGIN_V_FIELD, "Effect", TEXT_FIELD);
|
||||
private static final Set<String> REQUIRED_EVENT_FIELDS = Set.of(START_FIELD, END_FIELD, STYLE_FIELD, TEXT_FIELD);
|
||||
|
||||
private static final Pattern NEWLINE_PATTERN = Pattern.compile("\\n");
|
||||
private static final Pattern POS_PATTERN = Pattern.compile("^\\{\\\\pos\\((?<x>\\d+),(?<y>\\d+)\\)}");
|
||||
private static final Pattern START_DIALOG_PATTERN = Pattern.compile("^Dialogue: ");
|
||||
private static final Pattern START_ZERO_PATTERN = Pattern.compile("^0+");
|
||||
private static final Pattern PLAY_RES_Y_PATTERN = Pattern.compile("^PlayResY: (?<height>\\d+)", Pattern.MULTILINE);
|
||||
|
||||
private final Map<String, Translator<?>> translators;
|
||||
|
||||
@Inject
|
||||
@@ -45,22 +71,32 @@ public class ASSSubtitleConverter implements SubtitleConverter<SubtitleImpl> {
|
||||
@Override
|
||||
public String format(final SubtitleCollection<?> collection, final FormatOptions options) {
|
||||
final var subtitles = collection.subtitles().stream().sorted(Comparator.comparing(Subtitle::start).thenComparing(Subtitle::end)).toList();
|
||||
final var scriptInfo = getScriptInfo(options.videoInfo());
|
||||
final var styles = getStyles(subtitles, options.defaultFont());
|
||||
final var events = getEvents(subtitles, options.defaultFont());
|
||||
final var scriptInfo = writeScriptInfo(options.videoInfo());
|
||||
final var styles = writeStyles(subtitles, options.defaultFont());
|
||||
final var events = writeEvents(subtitles, options.defaultFont());
|
||||
return scriptInfo + "\n\n" + styles + "\n\n" + events + "\n";
|
||||
}
|
||||
|
||||
private static String getEvents(final Collection<? extends Subtitle> subtitles, final Font defaultFont) {
|
||||
return EVENTS_SECTION + "\n" + "Format: Start, End, Style, Text\n" +
|
||||
subtitles.stream().map(s -> getEvent(s, defaultFont)).collect(Collectors.joining("\n"));
|
||||
private static String writeEvents(final Collection<? extends Subtitle> subtitles, final Font defaultFont) {
|
||||
return EVENTS_SECTION + "\n" + "Format: " + String.join(", ", EVENT_FIELDS) + "\n" +
|
||||
subtitles.stream().map(s -> writeEvent(s, defaultFont)).collect(Collectors.joining("\n"));
|
||||
}
|
||||
|
||||
private static String getEvent(final Subtitle subtitle, final Font defaultFont) {
|
||||
return DIALOGUE + " " + formatTime(subtitle.start()) + "," + formatTime(subtitle.end()) + "," + getName(subtitle.font(), defaultFont) + "," + subtitle.content();
|
||||
private static String writeEvent(final Subtitle subtitle, final Font defaultFont) {
|
||||
return DIALOGUE + " 0," +
|
||||
formatTime(subtitle.start()) + "," +
|
||||
formatTime(subtitle.end()) + "," +
|
||||
getStyleName(subtitle.font(), defaultFont) + "," +
|
||||
"X," +
|
||||
"0000," +
|
||||
"0000," +
|
||||
"0000," +
|
||||
"," +
|
||||
(subtitle.bounds() == null ? "" : "{\\pos(" + (long) subtitle.bounds().x() + "," + (long) subtitle.bounds().y() + ")}") +
|
||||
subtitle.content();
|
||||
}
|
||||
|
||||
private static String getName(final Font font, final Font defaultFont) {
|
||||
private static String getStyleName(final Font font, final Font defaultFont) {
|
||||
final String fontName;
|
||||
final int fontSize;
|
||||
if (font == null) {
|
||||
@@ -73,7 +109,7 @@ public class ASSSubtitleConverter implements SubtitleConverter<SubtitleImpl> {
|
||||
return fontName + fontSize;
|
||||
}
|
||||
|
||||
private static String getStyles(final Collection<? extends Subtitle> subtitles, final Font defaultFont) {
|
||||
private static String writeStyles(final Collection<? extends Subtitle> subtitles, final Font defaultFont) {
|
||||
return STYLES_SECTION + "\n" + "Format: Name, Fontname, Fontsize\n" + listStyles(subtitles, defaultFont);
|
||||
}
|
||||
|
||||
@@ -82,10 +118,10 @@ public class ASSSubtitleConverter implements SubtitleConverter<SubtitleImpl> {
|
||||
if (subtitles.stream().anyMatch(s -> s.font() == null)) {
|
||||
uniqueStyles.add(defaultFont);
|
||||
}
|
||||
return uniqueStyles.stream().map(f -> STYLE + " " + getName(f, defaultFont) + ", " + f.name() + ", " + f.size()).collect(Collectors.joining("\n"));
|
||||
return uniqueStyles.stream().map(f -> STYLE + " " + getStyleName(f, defaultFont) + ", " + f.name() + ", " + f.size()).collect(Collectors.joining("\n"));
|
||||
}
|
||||
|
||||
private static String getScriptInfo(final VideoInfo videoInfo) {
|
||||
private static String writeScriptInfo(final VideoInfo videoInfo) {
|
||||
return """
|
||||
[Script Info]
|
||||
PlayResX: %d
|
||||
@@ -95,72 +131,127 @@ public class ASSSubtitleConverter implements SubtitleConverter<SubtitleImpl> {
|
||||
|
||||
@Override
|
||||
public SubtitleCollectionImpl<SubtitleImpl> parse(final String content, final ParseOptions options) throws ParseException {
|
||||
final var fonts = parseFonts(content, options.defaultFont());
|
||||
final var subtitles = parseSubtitles(content, fonts);
|
||||
final var videoHeight = parseVideoHeight(content);
|
||||
final var fonts = parseFonts(content);
|
||||
final var subtitles = parseSubtitles(content, fonts, options.defaultFont(), videoHeight);
|
||||
final var text = subtitles.stream().map(Subtitle::content).collect(Collectors.joining());
|
||||
final var language = translators.values().iterator().next().getLanguage(text); //Use any translator for now
|
||||
return new SubtitleCollectionImpl<>(text, subtitles, language);
|
||||
}
|
||||
|
||||
private static List<SubtitleImpl> parseSubtitles(final String content, final Map<String, ? extends Font> fonts) throws ParseException {
|
||||
final var fontIndex = content.indexOf(EVENTS_SECTION);
|
||||
if (fontIndex == -1) {
|
||||
private static int parseVideoHeight(final CharSequence content) {
|
||||
final var matcher = PLAY_RES_Y_PATTERN.matcher(content);
|
||||
if (matcher.find()) {
|
||||
return Integer.parseInt(matcher.group("height"));
|
||||
} else {
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
|
||||
private static List<SubtitleImpl> parseSubtitles(final String content, final Map<String, Font> fonts, final Font defaultFont, final int videoHeight) throws ParseException {
|
||||
final var eventsIndex = content.indexOf(EVENTS_SECTION);
|
||||
if (eventsIndex == -1) {
|
||||
throw new ParseException("Events section not found in " + content);
|
||||
} else {
|
||||
final var split = NEWLINE_PATTERN.split(content.substring(fontIndex));
|
||||
final List<String> fields;
|
||||
if (split[0].startsWith(EVENTS_SECTION)) {
|
||||
fields = getFields(split[1]);
|
||||
} else {
|
||||
throw new ParseException("Couldn't parse events : " + content);
|
||||
final var split = NEWLINE_PATTERN.split(content.substring(eventsIndex));
|
||||
final var fields = getFields(split[1]);
|
||||
final var fieldsMapping = EVENT_FIELDS.stream().collect(Collectors.toMap(e -> e, fields::indexOf));
|
||||
if (REQUIRED_EVENT_FIELDS.stream().anyMatch(s -> fieldsMapping.get(s) == -1)) {
|
||||
throw new ParseException("Missing required fields : " + content);
|
||||
}
|
||||
final var startIndex = fields.indexOf("Start");
|
||||
final var endIndex = fields.indexOf("End");
|
||||
final var styleIndex = fields.indexOf("Style");
|
||||
final var textIndex = fields.indexOf("Text");
|
||||
if (startIndex == -1 || endIndex == -1 || styleIndex == -1 || textIndex == -1) {
|
||||
throw new ParseException("Couldn't parse events : " + content);
|
||||
if (fieldsMapping.get("Text") != fields.size() - 1) {
|
||||
throw new ParseException("Text field should be the last field : " + content);
|
||||
}
|
||||
//Ignore effect for now
|
||||
return Arrays.stream(split).filter(s -> s.startsWith(DIALOGUE))
|
||||
.map(s -> {
|
||||
final var values = Arrays.stream(s.replace(DIALOGUE, "").split(",")).map(String::trim).filter(w -> !w.isBlank()).toList();
|
||||
final var start = parseTime(values.get(startIndex));
|
||||
final var end = parseTime(values.get(endIndex));
|
||||
final var style = values.get(styleIndex);
|
||||
final var font = fonts.get(style);
|
||||
final var text = values.stream().skip(textIndex).collect(Collectors.joining(", "));
|
||||
return new SubtitleImpl(text, start, end, font, null); //TODO pos style overrides
|
||||
final var values = parseValues(s, fields.size());
|
||||
final var start = parseTime(values.get(fieldsMapping.get(START_FIELD)));
|
||||
final var end = parseTime(values.get(fieldsMapping.get(END_FIELD)));
|
||||
final var style = values.get(fieldsMapping.get(STYLE_FIELD));
|
||||
final var marginBounds = getMarginBounds(values, fieldsMapping, videoHeight);
|
||||
final var font = fonts.getOrDefault(style, defaultFont);
|
||||
final var rawText = values.get(fieldsMapping.get(TEXT_FIELD));
|
||||
final var matcher = POS_PATTERN.matcher(rawText);
|
||||
if (matcher.find()) {
|
||||
final var x = Integer.parseInt(matcher.group("x"));
|
||||
final var y = Integer.parseInt(matcher.group("y"));
|
||||
final var bounds = new BoundsImpl(x, y, 0, 0);
|
||||
final var text = matcher.replaceAll("");
|
||||
return new SubtitleImpl(text, start, end, font, bounds);
|
||||
} else {
|
||||
return new SubtitleImpl(rawText, start, end, font, marginBounds);
|
||||
}
|
||||
}).toList();
|
||||
}
|
||||
}
|
||||
|
||||
private static Map<String, Font> parseFonts(final String content, final Font defaultFont) throws ParseException {
|
||||
final var fontIndex = content.indexOf(STYLES_SECTION);
|
||||
if (fontIndex == -1) {
|
||||
private static List<String> parseValues(final CharSequence value, final int size) {
|
||||
final var trimmed = START_DIALOG_PATTERN.matcher(value).replaceAll("").trim();
|
||||
final var values = new ArrayList<String>(EVENT_FIELDS.size());
|
||||
var substring = trimmed;
|
||||
while (!substring.isEmpty()) {
|
||||
final var index = substring.indexOf(',');
|
||||
if (index == -1 || values.size() == size - 1) {
|
||||
values.add(substring);
|
||||
substring = "";
|
||||
} else {
|
||||
values.add(substring.substring(0, index));
|
||||
substring = substring.substring(index + 1);
|
||||
}
|
||||
}
|
||||
return values;
|
||||
}
|
||||
|
||||
private static Bounds getMarginBounds(final List<String> values, final Map<String, Integer> fieldsMapping, final int videoHeight) {
|
||||
final var marginLIndex = fieldsMapping.get(MARGIN_L_FIELD);
|
||||
final var marginRIndex = fieldsMapping.get(MARGIN_R_FIELD);
|
||||
final var marginVIndex = fieldsMapping.get(MARGIN_V_FIELD);
|
||||
if (marginLIndex == -1 || marginRIndex == -1 || marginVIndex == -1) {
|
||||
return null;
|
||||
} else {
|
||||
final var marginL = parseMargin(values.get(marginLIndex));
|
||||
final var marginR = parseMargin(values.get(marginRIndex));
|
||||
final var marginV = parseMargin(values.get(marginVIndex));
|
||||
if (marginL == -1 || marginR == -1 || marginV == -1) {
|
||||
return null;
|
||||
} else {
|
||||
final var y = videoHeight <= 0 ? 0 : videoHeight - marginV;
|
||||
return new BoundsImpl(marginL, y, marginR - (double) marginL, 0);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private static int parseMargin(final CharSequence margin) {
|
||||
final var removedZero = START_ZERO_PATTERN.matcher(margin).replaceAll("");
|
||||
return removedZero.isEmpty() ? -1 : Integer.parseInt(removedZero);
|
||||
}
|
||||
|
||||
private static Map<String, Font> parseFonts(final String content) throws ParseException {
|
||||
final var stylesIndex = content.indexOf(STYLES_SECTION);
|
||||
if (stylesIndex == -1) {
|
||||
throw new ParseException("Styles section not found in " + content);
|
||||
} else {
|
||||
final var split = NEWLINE_PATTERN.split(content.substring(fontIndex));
|
||||
final List<String> fields;
|
||||
if (split[0].startsWith(STYLES_SECTION)) {
|
||||
fields = getFields(split[1]);
|
||||
} else {
|
||||
throw new ParseException("Couldn't parse styles : " + content);
|
||||
}
|
||||
final var fontNameIndex = fields.indexOf("Fontname");
|
||||
final var fontSizeIndex = fields.indexOf("Fontsize");
|
||||
if (fontNameIndex == -1 || fontSizeIndex == -1) {
|
||||
throw new ParseException("Couldn't parse styles : " + content);
|
||||
final var split = NEWLINE_PATTERN.split(content.substring(stylesIndex));
|
||||
final var fields = getFields(split[1]);
|
||||
final var fieldsMapping = STYLE_FIELDS.stream().collect(Collectors.toMap(e -> e, fields::indexOf));
|
||||
if (REQUIRED_STYLE_FIELDS.stream().anyMatch(s -> fieldsMapping.get(s) == -1)) {
|
||||
throw new ParseException("Missing required fields : " + content);
|
||||
}
|
||||
return Arrays.stream(split).filter(s -> s.startsWith(STYLE))
|
||||
.map(s -> {
|
||||
final var values = Arrays.stream(s.replace(STYLE, "").split(",")).map(String::trim).filter(w -> !w.isBlank()).toList();
|
||||
final var name = values.get(fontNameIndex);
|
||||
final var size = Integer.parseInt(values.get(fontSizeIndex));
|
||||
return new FontImpl(name, size);
|
||||
}).collect(Collectors.toMap(f -> getName(f, defaultFont), f -> f));
|
||||
final var name = values.get(fieldsMapping.get(NAME_FIELD));
|
||||
final var fontName = values.get(fieldsMapping.get(FONTNAME_FIELD));
|
||||
final var fontSize = Integer.parseInt(values.get(fieldsMapping.get(FONTSIZE_FIELD)));
|
||||
return new NamedFont(name, new FontImpl(fontName, fontSize));
|
||||
}).collect(Collectors.toMap(f -> f.name, f -> f.font));
|
||||
}
|
||||
}
|
||||
|
||||
private record NamedFont(String name, Font font) {
|
||||
}
|
||||
|
||||
private static List<String> getFields(final String string) {
|
||||
return Arrays.stream(string.replace(FORMAT, "").split(",")).map(String::trim).filter(s -> !s.isBlank()).toList();
|
||||
}
|
||||
|
||||
@@ -6,6 +6,7 @@ import com.github.gtache.autosubtitle.subtitle.Subtitle;
|
||||
import com.github.gtache.autosubtitle.subtitle.converter.FormatOptions;
|
||||
import com.github.gtache.autosubtitle.subtitle.converter.ParseException;
|
||||
import com.github.gtache.autosubtitle.subtitle.converter.ParseOptions;
|
||||
import com.github.gtache.autosubtitle.subtitle.impl.BoundsImpl;
|
||||
import com.github.gtache.autosubtitle.subtitle.impl.FontImpl;
|
||||
import com.github.gtache.autosubtitle.subtitle.impl.SubtitleCollectionImpl;
|
||||
import com.github.gtache.autosubtitle.subtitle.impl.SubtitleImpl;
|
||||
@@ -13,10 +14,14 @@ import com.github.gtache.autosubtitle.translation.Translator;
|
||||
import org.junit.jupiter.api.BeforeEach;
|
||||
import org.junit.jupiter.api.Test;
|
||||
import org.junit.jupiter.api.extension.ExtendWith;
|
||||
import org.junit.jupiter.params.ParameterizedTest;
|
||||
import org.junit.jupiter.params.provider.ValueSource;
|
||||
import org.mockito.Mock;
|
||||
import org.mockito.junit.jupiter.MockitoExtension;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.Arrays;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
|
||||
import static java.util.Objects.requireNonNull;
|
||||
@@ -56,6 +61,28 @@ class TestASSSubtitleConverter {
|
||||
when(translator.getLanguage(anyString())).thenReturn(language);
|
||||
}
|
||||
|
||||
@Test
|
||||
void testFormatDefaultFont() {
|
||||
final var font = new FontImpl("Times New Roman", 13);
|
||||
when(formatOptions.defaultFont()).thenReturn(font);
|
||||
final var subtitle = new SubtitleImpl("Test", 0, 1000, null, null);
|
||||
final var expected = """
|
||||
[Script Info]
|
||||
PlayResX: 1920
|
||||
PlayResY: 1080
|
||||
WrapStyle: 1
|
||||
|
||||
[V4+ Styles]
|
||||
Format: Name, Fontname, Fontsize
|
||||
Style: Times New Roman13, Times New Roman, 13
|
||||
|
||||
[Events]
|
||||
Format: Layer, Start, End, Style, Name, MarginL, MarginR, MarginV, Effect, Text
|
||||
Dialogue: 0,00:00:00.00,00:00:01.00,Times New Roman13,X,0000,0000,0000,,Test
|
||||
""";
|
||||
assertEquals(expected, converter.format(new SubtitleCollectionImpl<>(subtitle.content(), List.of(subtitle), language), formatOptions));
|
||||
}
|
||||
|
||||
@Test
|
||||
void testParseFormat() throws ParseException {
|
||||
final var in = """
|
||||
@@ -70,24 +97,119 @@ class TestASSSubtitleConverter {
|
||||
Style: Arial12, Arial, 12
|
||||
|
||||
[Events]
|
||||
Format: Start, End, Style, Text
|
||||
Dialogue: 00:00:00.00,00:00:00.41,Arial12,Test ?
|
||||
Dialogue: 123:45:54.32,124:00:00.00,Times New Roman13,Test2.
|
||||
Format: Layer, Start, End, Style, Name, MarginL, MarginR, MarginV, Effect, Text
|
||||
Dialogue: 0,00:00:00.00,00:00:00.41,Arial12,X,0000,0000,0000,,Test ?
|
||||
Dialogue: 0,00:00:00.00,00:00:00.54,Arial12,X,0000,0000,0000,,{\\pos(1000,880)}Testmargin
|
||||
Dialogue: 0,00:00:00.00,00:00:11.00,Arial12,X,0000,0000,0000,,{\\pos(800,600)}Testpos
|
||||
Dialogue: 0,123:45:54.32,124:00:00.00,Times New Roman13,X,0000,0000,0000,,Test2.
|
||||
""";
|
||||
|
||||
final var start1 = 0L;
|
||||
final var end1 = 410L;
|
||||
final var start2 = 123 * 3600 * 1000 + 45 * 60 * 1000 + 54 * 1000 + 320;
|
||||
final var end2 = 124 * 3600 * 1000;
|
||||
final var end2 = 540L;
|
||||
final var end3 = 11000L;
|
||||
final var start4 = 123 * 3600 * 1000 + 45 * 60 * 1000 + 54 * 1000 + 320;
|
||||
final var end4 = 124 * 3600 * 1000;
|
||||
final var arial = new FontImpl("Arial", 12);
|
||||
final var times = new FontImpl("Times New Roman", 13);
|
||||
final var subtitle1 = new SubtitleImpl("Test ?", start1, end1, arial, null);
|
||||
final var subtitle2 = new SubtitleImpl("Test2.", start2, end2, times, null);
|
||||
final var subtitles = new SubtitleCollectionImpl<>(subtitle1.content() + subtitle2.content(), Arrays.asList(subtitle1, subtitle2), language);
|
||||
final var subtitle2 = new SubtitleImpl("Testmargin", start1, end2, arial, new BoundsImpl(1000, 880, 0, 0));
|
||||
final var subtitle3 = new SubtitleImpl("Testpos", start1, end3, arial, new BoundsImpl(800, 600, 0, 0));
|
||||
final var subtitle4 = new SubtitleImpl("Test2.", start4, end4, times, null);
|
||||
final var subtitles = new SubtitleCollectionImpl<>(subtitle1.content() + subtitle2.content()
|
||||
+ subtitle3.content() + subtitle4.content(), List.of(subtitle1, subtitle2, subtitle3, subtitle4), language);
|
||||
assertEquals(subtitles, converter.parse(in, parseOptions));
|
||||
assertEquals(in, converter.format(subtitles, formatOptions));
|
||||
}
|
||||
|
||||
@Test
|
||||
void testParseMargin() throws ParseException {
|
||||
final var in = """
|
||||
[Script Info]
|
||||
PlayResX: 1920
|
||||
PlayResY: 1080
|
||||
WrapStyle: 1
|
||||
|
||||
[V4+ Styles]
|
||||
Format: Name, Fontname, Fontsize
|
||||
Style: Arial12, Arial, 12
|
||||
|
||||
[Events]
|
||||
Format: Layer, Start, End, Style, Name, MarginL, MarginR, MarginV, Effect, Text
|
||||
Dialogue: 0,00:00:00.00,00:00:00.54,Arial12,X,1000,1500,0200,,Testmargin
|
||||
""";
|
||||
|
||||
final var start = 0L;
|
||||
final var end = 540L;
|
||||
final var arial = new FontImpl("Arial", 12);
|
||||
final var subtitle = new SubtitleImpl("Testmargin", start, end, arial, new BoundsImpl(1000, 880, 500, 0));
|
||||
final var subtitles = new SubtitleCollectionImpl<>(subtitle.content(), List.of(subtitle), language);
|
||||
assertEquals(subtitles, converter.parse(in, parseOptions));
|
||||
|
||||
final var out = """
|
||||
[Script Info]
|
||||
PlayResX: 1920
|
||||
PlayResY: 1080
|
||||
WrapStyle: 1
|
||||
|
||||
[V4+ Styles]
|
||||
Format: Name, Fontname, Fontsize
|
||||
Style: Arial12, Arial, 12
|
||||
|
||||
[Events]
|
||||
Format: Layer, Start, End, Style, Name, MarginL, MarginR, MarginV, Effect, Text
|
||||
Dialogue: 0,00:00:00.00,00:00:00.54,Arial12,X,0000,0000,0000,,{\\pos(1000,880)}Testmargin
|
||||
""";
|
||||
assertEquals(out, converter.format(subtitles, formatOptions));
|
||||
}
|
||||
|
||||
@Test
|
||||
void testParseMarginNoSize() throws ParseException {
|
||||
final var in = """
|
||||
[Script Info]
|
||||
WrapStyle: 1
|
||||
|
||||
[V4+ Styles]
|
||||
Format: Name, Fontname, Fontsize
|
||||
Style: Arial12, Arial, 12
|
||||
|
||||
[Events]
|
||||
Format: Layer, Start, End, Style, Name, MarginL, MarginR, MarginV, Effect, Text
|
||||
Dialogue: 0,00:00:00.00,00:00:00.54,Arial12,X,1000,1500,0200,,Testmargin
|
||||
""";
|
||||
|
||||
final var start = 0L;
|
||||
final var end = 540L;
|
||||
final var arial = new FontImpl("Arial", 12);
|
||||
final var subtitle = new SubtitleImpl("Testmargin", start, end, arial, new BoundsImpl(1000, 0, 500, 0));
|
||||
final var subtitles = new SubtitleCollectionImpl<>(subtitle.content(), List.of(subtitle), language);
|
||||
assertEquals(subtitles, converter.parse(in, parseOptions));
|
||||
}
|
||||
|
||||
@Test
|
||||
void testParseUnknownFont() throws ParseException {
|
||||
final var defaultFont = new FontImpl("Times New Roman", 13);
|
||||
when(parseOptions.defaultFont()).thenReturn(defaultFont);
|
||||
final var in = """
|
||||
[Script Info]
|
||||
WrapStyle: 1
|
||||
|
||||
[V4+ Styles]
|
||||
Format: Name, Fontname, Fontsize
|
||||
Style: Arial12, Arial, 12
|
||||
|
||||
[Events]
|
||||
Format: Layer, Start, End, Style, Name, MarginL, MarginR, MarginV, Effect, Text
|
||||
Dialogue: 0,00:00:00.00,00:00:00.54,blabla,X,1000,1500,0200,,Testmargin
|
||||
""";
|
||||
|
||||
final var start = 0L;
|
||||
final var end = 540L;
|
||||
final var subtitle = new SubtitleImpl("Testmargin", start, end, defaultFont, new BoundsImpl(1000, 0, 500, 0));
|
||||
final var subtitles = new SubtitleCollectionImpl<>(subtitle.content(), List.of(subtitle), language);
|
||||
assertEquals(subtitles, converter.parse(in, parseOptions));
|
||||
}
|
||||
|
||||
@Test
|
||||
void testParseDifferentFormat() throws ParseException {
|
||||
final var in = """
|
||||
@@ -119,6 +241,110 @@ class TestASSSubtitleConverter {
|
||||
assertEquals(subtitles, converter.parse(in, parseOptions));
|
||||
}
|
||||
|
||||
@Test
|
||||
void testParseNoEvents() {
|
||||
final var in = """
|
||||
[Script Info]
|
||||
PlayResX: 1920
|
||||
PlayResY: 1080
|
||||
WrapStyle: 1
|
||||
|
||||
[V4+ Styles]
|
||||
Format: Name, Fontsize, Fontname
|
||||
Style: Arial12, 12, Arial
|
||||
""";
|
||||
assertThrows(ParseException.class, () -> converter.parse(in, parseOptions));
|
||||
}
|
||||
|
||||
@Test
|
||||
void testParseNoStyles() {
|
||||
final var in = """
|
||||
[Script Info]
|
||||
PlayResX: 1920
|
||||
PlayResY: 1080
|
||||
WrapStyle: 1
|
||||
|
||||
[Events]
|
||||
Format: Style, End, Start, Text
|
||||
Dialogue: Arial12,0:00:00.41,0:00:00.00,Test ?
|
||||
Dialogue: Times New Roman13,124:00:00.00,123:45:54.32,Test2.
|
||||
""";
|
||||
assertThrows(ParseException.class, () -> converter.parse(in, parseOptions));
|
||||
}
|
||||
|
||||
@ParameterizedTest
|
||||
@ValueSource(strings = {"Name", "Fontsize", "Fontname"})
|
||||
void testParseMissingRequiredStyleFields(final String missing) {
|
||||
final var present = new ArrayList<String>();
|
||||
present.add("Name");
|
||||
present.add("Fontname");
|
||||
present.add("Fontsize");
|
||||
present.remove(missing);
|
||||
final var in = """
|
||||
[Script Info]
|
||||
PlayResX: 1920
|
||||
PlayResY: 1080
|
||||
WrapStyle: 1
|
||||
|
||||
[V4+ Styles]
|
||||
Format: %s
|
||||
Style: Arial12, 12, Arial
|
||||
|
||||
[Events]
|
||||
Format: Start, End, Text, Style
|
||||
Dialogue: Arial12,0:00:00.41,0:00:00.00,Test ?
|
||||
Dialogue: Times New Roman13,124:00:00.00,123:45:54.32,Test2.
|
||||
""".formatted(String.join(", ", present));
|
||||
assertThrows(ParseException.class, () -> converter.parse(in, parseOptions));
|
||||
}
|
||||
|
||||
@ParameterizedTest
|
||||
@ValueSource(strings = {"Start", "End", "Style", "Text"})
|
||||
void testParseMissingRequiredEventFields(final String missing) {
|
||||
final var present = new ArrayList<String>();
|
||||
present.add("Start");
|
||||
present.add("End");
|
||||
present.add("Style");
|
||||
present.add("Text");
|
||||
present.remove(missing);
|
||||
final var in = """
|
||||
[Script Info]
|
||||
PlayResX: 1920
|
||||
PlayResY: 1080
|
||||
WrapStyle: 1
|
||||
|
||||
[V4+ Styles]
|
||||
Format: Name, Fontsize, Fontname
|
||||
Style: Arial12, 12, Arial
|
||||
|
||||
[Events]
|
||||
Format: %s
|
||||
Dialogue: Arial12,0:00:00.41,0:00:00.00,Test ?
|
||||
Dialogue: Times New Roman13,124:00:00.00,123:45:54.32,Test2.
|
||||
""".formatted(String.join(", ", present));
|
||||
assertThrows(ParseException.class, () -> converter.parse(in, parseOptions));
|
||||
}
|
||||
|
||||
@Test
|
||||
void testParseTextNotLast() {
|
||||
final var in = """
|
||||
[Script Info]
|
||||
PlayResX: 1920
|
||||
PlayResY: 1080
|
||||
WrapStyle: 1
|
||||
|
||||
[V4+ Styles]
|
||||
Format: Name, Fontsize, Fontname
|
||||
Style: Arial12, 12, Arial
|
||||
|
||||
[Events]
|
||||
Format: Start, End, Text, Style
|
||||
Dialogue: Arial12,0:00:00.41,0:00:00.00,Test ?
|
||||
Dialogue: Times New Roman13,124:00:00.00,123:45:54.32,Test2.
|
||||
""";
|
||||
assertThrows(ParseException.class, () -> converter.parse(in, parseOptions));
|
||||
}
|
||||
|
||||
@Test
|
||||
void testParseException() {
|
||||
final var in = """
|
||||
|
||||
2071
documentation/ASS File Format Specification.htm
Normal file
2071
documentation/ASS File Format Specification.htm
Normal file
File diff suppressed because it is too large
Load Diff
814
documentation/Subtitles.htm
Normal file
814
documentation/Subtitles.htm
Normal file
@@ -0,0 +1,814 @@
|
||||
<!DOCTYPE html>
|
||||
<html><head>
|
||||
<meta http-equiv="content-type" content="text/html; charset=UTF-8">
|
||||
<meta charset="utf-8">
|
||||
<meta http-equiv="X-UA-Compatible" content="IE=edge">
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1">
|
||||
|
||||
<title>Subtitles</title>
|
||||
<meta name="description" content="">
|
||||
|
||||
<link rel="shortcut icon" href="https://www.matroska.org/images/favicon.ico" type="image/vnd.microsoft.icon">
|
||||
<link rel="stylesheet" href="Subtitles_files/bootstrap.min.css" integrity="sha384-1q8mTJOASx8j1Au+a5WDVnPi2lkFfwwEAa8hDDdjZlpLegxhjVME1fgjWPGmkzs7" crossorigin="anonymous">
|
||||
<link rel="stylesheet" href="Subtitles_files/main.css">
|
||||
<link rel="canonical" href="https://www.matroska.org/technical/subtitles.html">
|
||||
</head>
|
||||
|
||||
<body>
|
||||
<header class="site-header">
|
||||
<div class="wrapper">
|
||||
<a class="site-title" href="https://www.matroska.org/"><img src="Subtitles_files/logo.png" alt="The Matroska Media Container logo"></a>
|
||||
<nav class="site-nav">
|
||||
</nav>
|
||||
</div>
|
||||
</header>
|
||||
|
||||
<div class="container-fluid">
|
||||
<div class="sidebar col-md-2">
|
||||
<h2 class="block__title block-title">Menu</h2>
|
||||
|
||||
<ul>
|
||||
<li><a href="https://www.matroska.org/" title="Start page">Home</a></li>
|
||||
<li><a href="https://www.matroska.org/what_is_matroska.html" title="What is Matroska?">What is Matroska?</a></li>
|
||||
<li>Downloads
|
||||
<ul>
|
||||
<li><a href="https://www.matroska.org/downloads/mkclean.html" title="mkclean">mkclean</a></li>
|
||||
<li><a href="https://www.matroska.org/downloads/mkvalidator.html" title="mkvalidator">mkvalidator</a></li>
|
||||
<li><a href="https://www.matroska.org/downloads/libraries.html" title="libraries">libraries</a></li>
|
||||
<li><a href="https://www.matroska.org/downloads/mkvtoolnix.html" title="MKVToolNix">MKVToolNix</a></li>
|
||||
<li><a href="https://www.matroska.org/downloads/third_party.html" title="Third-party applications">Third-party applications</a></li>
|
||||
<li><a href="https://www.matroska.org/downloads/test_suite.html" title="Test suite">Test suite</a></li>
|
||||
</ul>
|
||||
</li>
|
||||
<li><a href="https://www.matroska.org/source_code_repositories.html" title="Source code repositories">Source code repositories</a></li>
|
||||
<li><a href="https://www.matroska.org/faq.html" title="FAQ">FAQ</a></li>
|
||||
|
||||
<li><a href="https://www.matroska.org/index.html" title="Technical Details">Technical / Info</a>
|
||||
<ul>
|
||||
<li><a href="https://www.matroska.org/technical/basics.html" title="Basics">Basics</a></li>
|
||||
<li><a href="https://www.matroska.org/technical/diagram.html" title="Data Layout">Data Layout</a></li>
|
||||
<li><a href="https://www.matroska.org/technical/elements.html" title="Element Specifications">Element Specifications</a></li>
|
||||
<li><a href="https://www.matroska.org/technical/notes.html" title="Specification Notes">Specification Notes</a></li>
|
||||
<li><a href="https://www.matroska.org/technical/ordering.html" title="EBML Element Ordering">Element Ordering</a></li>
|
||||
<li><a href="https://www.matroska.org/technical/chapters.html" title="Chapter Specifications">Chapters</a></li>
|
||||
<li><a href="https://www.matroska.org/technical/menu.html" title="Menu Specifications">Menu</a></li>
|
||||
<li><a href="https://www.matroska.org/technical/chapter_codecs.html" title="Chapter Codecs">Chapter Codecs</a></li>
|
||||
<li><a href="https://www.matroska.org/technical/attachments.html" title="Attachments">Attachments</a></li>
|
||||
<li><a href="https://www.matroska.org/technical/cues.html" title="Cues">Cues</a></li>
|
||||
<li><a href="https://www.matroska.org/technical/streaming.html" title="Matroska Streaming">Streaming</a></li>
|
||||
<li><a href="https://www.matroska.org/technical/codec_specs.html" title="Codec Mapping">Codec Mapping</a></li>
|
||||
<li><a href="https://www.matroska.org/technical/subtitles.html" title="Subtitles">Subtitles</a></li>
|
||||
<li><a href="https://www.matroska.org/technical/block_additional_mappings.html" title="Block Additional Mappings">Block Additional Mappings</a></li>
|
||||
<li>
|
||||
<a href="https://www.matroska.org/technical/tagging.html" title="Tag Specifications">Tags</a>
|
||||
<ul>
|
||||
<li><a href="https://www.matroska.org/technical/tagging-audio-example.html" title="Audio Tags Example">Audio Examples</a></li>
|
||||
<li><a href="https://www.matroska.org/technical/tagging-video-example.html" title="Video Tags Example">Video Examples</a></li>
|
||||
<li><a href="https://www.matroska.org/technical/tags-precedence.html" title="Tags Precedence">Tags Precedence</a></li>
|
||||
</ul>
|
||||
</li>
|
||||
<li><a href="https://www.matroska.org/technical/matroska_implement.html" title="Implementation Recommendations">Implementation Recommendations</a></li>
|
||||
<li><a href="https://www.matroska.org/technical/ebml_rfc.html" title="EBML RFC">EBML RFC</a></li>
|
||||
</ul>
|
||||
</li>
|
||||
|
||||
<li><a href="https://www.matroska.org/contributors.html" title="Contributors">Contributors</a></li>
|
||||
<li><a href="https://www.matroska.org/license.html" title="License">License</a></li>
|
||||
<li><a href="https://www.matroska.org/legal.html" title="Legal aspects">Legal aspects</a></li>
|
||||
<li><a href="https://www.matroska.org/logos_trademarks.html" title="Logos & trademarks">Logos & trademarks</a></li>
|
||||
<li><a href="https://www.matroska.org/contact.html" title="Contact">Contact</a></li>
|
||||
</ul>
|
||||
|
||||
</div>
|
||||
<div class="page-content col-md-10">
|
||||
<div class="wrapper">
|
||||
<h1 id="subtitles">Subtitles</h1>
|
||||
|
||||
<p>Because Matroska is a general container format, we try to avoid specifying the formats
|
||||
to store in it. This type of work is really outside of the scope of a container-only format.
|
||||
However, because the use of subtitles in A/V containers has been so limited (with the exception of DVD)
|
||||
we are taking the time to specify how to store some of the more common subtitle formats in Matroska.
|
||||
This is being done to help facilitate their growth. Otherwise, incompatibilities could prevent
|
||||
the standardization and use of subtitle storage.</p>
|
||||
|
||||
<p>This page is not meant to be a complete listing of all subtitle formats that will be used in Matroska,
|
||||
it is only meant to be a guide for the more common, current formats. It is possible that
|
||||
we will add future formats to this page as they are created, but it is not likely as any
|
||||
other new subtitle format designer would likely have their own specifications.
|
||||
Any specification listed here <strong>SHOULD</strong> be strictly adhered to or it <strong>SHOULD NOT</strong>
|
||||
use the corresponding Codec ID.</p>
|
||||
|
||||
<p>Here is a list of pointers for storing subtitles in Matroska:</p>
|
||||
|
||||
<ul>
|
||||
<li>Any Matroska file containing only subtitles <strong>SHOULD</strong> use the extension “.mks”.</li>
|
||||
<li>As a general rule of thumb for all codecs, information that is global to an entire stream
|
||||
<strong>SHOULD</strong> be stored in the CodecPrivate element.</li>
|
||||
<li>Start and stop timestamps that are used in a timestamps native storage format <strong>SHOULD</strong>
|
||||
be removed when being placed in Matroska as they could interfere if the file is edited
|
||||
afterwards. Instead, the Blocks timestamp and Duration <strong>SHOULD</strong> be used to say when the timestamp is displayed.</li>
|
||||
<li>Because a “subtitle” stream is actually just an overlay stream, anything with a transparency
|
||||
layer could be use, including video.</li>
|
||||
</ul>
|
||||
|
||||
<h2 id="images-subtitles">Images Subtitles</h2>
|
||||
|
||||
<p>The first image format that is a goal to import into Matroska is the VobSub subtitle format.
|
||||
This subtitle type is generated by exporting the subtitles from a DVD [@?DVD-Video].</p>
|
||||
|
||||
<p>The requirement for muxing VobSub into Matroska is v7 subtitles (see first line of the .IDX file).
|
||||
If the version is smaller, you must remux them using the SubResync utility from
|
||||
VobSub 2.23 (or MPC) into v7 format. Generally any newly created subs will be in v7 format.</p>
|
||||
|
||||
<p>The .IFO file will not be used at all.</p>
|
||||
|
||||
<p>If there is more than one subtitle stream in the VobSub set, each stream will need to be
|
||||
separated into separate tracks for storage in Matroska. E.g. the VobSub file contains
|
||||
streams for both English and German subtitles. Then the resulting Matroska file <strong>SHOULD</strong>
|
||||
contain two tracks. That way the language information can be dropped and mapped
|
||||
to Matroska’s language tags.</p>
|
||||
|
||||
<p>The .IDX file is reformatted (see below) and placed in the CodecPrivate.</p>
|
||||
|
||||
<p>Each .BMP will be stored in its own Block. The Timestamp with be stored in the Blocks Timestamp
|
||||
and the duration will be stored in the Default Duration.</p>
|
||||
|
||||
<p>Here is an example .IDX file:</p>
|
||||
|
||||
<pre><code class="language-vobsub"> # VobSub index file, v7 (do not modify this line!)
|
||||
#
|
||||
# To repair desynchronization, you can insert gaps this way:
|
||||
# (it usually happens after vob id changes)
|
||||
#
|
||||
# delay: [sign]hh:mm:ss:ms
|
||||
#
|
||||
# Where:
|
||||
# [sign]: +, - (optional)
|
||||
# hh: hours (0 <= hh)
|
||||
# mm/ss: minutes/seconds (0 <= mm/ss <= 59)
|
||||
# ms: milliseconds (0 <= ms <= 999)
|
||||
#
|
||||
# Note: You can't position a sub before the previous with a negative
|
||||
# value.
|
||||
#
|
||||
# You can also modify timestamps or delete a few subs you don't
|
||||
# like. Just make sure they stay in increasing order.
|
||||
|
||||
# Settings
|
||||
|
||||
# Original frame size
|
||||
size: 720x480
|
||||
|
||||
# Origin, relative to the upper-left corner, can be overloaded by
|
||||
# alignment
|
||||
org: 0, 0
|
||||
|
||||
# Image scaling (hor,ver), origin is at the upper-left corner or at
|
||||
# the alignment coord (x, y)
|
||||
scale: 100%, 100%
|
||||
|
||||
# Alpha blending
|
||||
alpha: 100%
|
||||
|
||||
# Smoothing for very blocky images (use OLD for no filtering)
|
||||
smooth: OFF
|
||||
|
||||
# In millisecs
|
||||
fadein/out: 50, 50
|
||||
|
||||
# Force subtitle placement relative to (org.x, org.y)
|
||||
align: OFF at LEFT TOP
|
||||
|
||||
# For correcting non-progressive desync. (in millisecs or
|
||||
# hh:mm:ss:ms)
|
||||
# Note: Not effective in DirectVobSub, use "delay: ... " instead.
|
||||
time offset: 0
|
||||
|
||||
# ON: displays only forced subtitles, OFF: shows everything
|
||||
forced subs: OFF
|
||||
|
||||
# The original palette of the DVD
|
||||
palette: 000000, 7e7e7e, fbff8b, cb86f1, 7f74b8, e23f06, 0a48ea, \
|
||||
b3d65a, 6b92f1, 87f087, c02081, f8d0f4, e3c411, 382201, e8840b, \
|
||||
fdfdfd
|
||||
|
||||
# Custom colors (transp idxs and the four colors)
|
||||
custom colors: OFF, tridx: 0000, colors: 000000, 000000, 000000, \
|
||||
000000
|
||||
|
||||
# Language index in use
|
||||
langidx: 0
|
||||
|
||||
# English
|
||||
id: en, index: 0
|
||||
# Uncomment next line to activate alternative name in DirectVobSub /
|
||||
# Windows Media Player 6.x
|
||||
# alt: English
|
||||
# Vob/Cell ID: 1, 1 (PTS: 0)
|
||||
timestamp: 00:00:01:101, filepos: 000000000
|
||||
timestamp: 00:00:08:708, filepos: 000001000
|
||||
</code></pre>
|
||||
|
||||
<p>First, lines beginning with “#” are removed. These are comments to make text file editing easier,
|
||||
and as this is not a text file, they aren’t needed.</p>
|
||||
|
||||
<p>Next remove the “langidx” and “id” lines. These are used to differentiate the subtitle
|
||||
streams and define the language. As the streams will be stored separately anyway,
|
||||
there is no need to differentiate them here. Also, the language setting will be stored
|
||||
in the Matroska tags, so there is no need to store it here.</p>
|
||||
|
||||
<p>Finally, the “timestamp” will be used to set the Block’s timestamp. Once it is set there,
|
||||
there is no need for it to be stored here. Also, as it may interfere if the file is edited,
|
||||
it <strong>SHOULD NOT</strong> be stored here.</p>
|
||||
|
||||
<p>Once all of these items are removed, the data to store in the CodecPrivate <strong>SHOULD</strong> look like this:</p>
|
||||
|
||||
<pre><code class="language-vobsub"> size: 720x480
|
||||
org: 0, 0
|
||||
scale: 100%, 100%
|
||||
alpha: 100%
|
||||
smooth: OFF
|
||||
fadein/out: 50, 50
|
||||
align: OFF at LEFT TOP
|
||||
time offset: 0
|
||||
forced subs: OFF
|
||||
palette: 000000, 7e7e7e, fbff8b, cb86f1, 7f74b8, e23f06, 0a48ea, \
|
||||
b3d65a, 6b92f1, 87f087, c02081, f8d0f4, e3c411, 382201, e8840b, \
|
||||
fdfdfd
|
||||
custom colors: OFF, tridx: 0000, colors: 000000, 000000, 000000, \
|
||||
000000
|
||||
</code></pre>
|
||||
|
||||
<p>There <strong>SHOULD</strong> also be two Blocks containing one image each with the timestamps “00:00:01:101” and “00:00:08:708”.</p>
|
||||
|
||||
<h2 id="srt-subtitles">SRT Subtitles</h2>
|
||||
|
||||
<p>SRT is perhaps the most basic of all subtitle formats.</p>
|
||||
|
||||
<p>It consists of four parts, all in text:</p>
|
||||
|
||||
<p>1. A number indicating which subtitle it is in the sequence.
|
||||
2. The time that the subtitle appears on the screen, and then disappears.
|
||||
3. The subtitle itself.
|
||||
4. A blank line indicating the start of a new subtitle.</p>
|
||||
|
||||
<p>When placing SRT in Matroska, part 3 is converted to UTF-8 (S_TEXT/UTF8) and placed
|
||||
in the data portion of the Block. Part 2 is used to set the timestamp of the Block,
|
||||
and BlockDuration element. Nothing else is used.</p>
|
||||
|
||||
<p>Here is an example SRT file:</p>
|
||||
|
||||
<pre><code class="language-srt">1
|
||||
00:02:17,440 --> 00:02:20,375
|
||||
Senator, we're making
|
||||
our final approach into Coruscant.
|
||||
|
||||
2
|
||||
00:02:20,476 --> 00:02:22,501
|
||||
Very good, Lieutenant.
|
||||
</code></pre>
|
||||
|
||||
<p>In this example, the text “Senator, we’re making our final approach into Coruscant.”
|
||||
would be converted into UTF-8 and placed in the Block. The timestamp of the block would
|
||||
be set to “00:02:17,440”. And the BlockDuration element would be set to “00:00:02,935”.</p>
|
||||
|
||||
<p>The same is repeated for the next subtitle.</p>
|
||||
|
||||
<p>Because there are no general settings for SRT, the CodecPrivate is left blank.</p>
|
||||
|
||||
<h2 id="ssaass-subtitles">SSA/ASS Subtitles</h2>
|
||||
|
||||
<p>SSA stands for Sub Station Alpha. It’s the file format used by the popular subtitle editor,
|
||||
<a href="http://wiki.multimedia.cx/index.php?title=SubStation_Alpha">SubStation Alpha</a>.
|
||||
This format is widely used by fansubbers.</p>
|
||||
|
||||
<p>It allows you to do some advanced display features, like positioning, karaoke, style managements…</p>
|
||||
|
||||
<p>For detailed information on SSA/ASS, see the <a href="http://moodub.free.fr/video/ass-specs.doc">SSA specs</a>.
|
||||
It includes an SSA specs description and the advanced features added by ASS format (standing for Advanced SSA).
|
||||
Because SSA and ASS are so similar, they are treated the same here.</p>
|
||||
|
||||
<p>Like SRT, this format is text based with a particular syntax.</p>
|
||||
|
||||
<p>A file consists of 4 or 5 parts, declared ala INI file (but it’s not an INI !)</p>
|
||||
|
||||
<p>The first, “[Script Info]” contains some information about the subtitle file,
|
||||
such as it’s title, who created it, type of script and a very important one: “PlayResY”.
|
||||
Be careful of this value, everything in your script (font size, positioning) is scaled by it.
|
||||
Sub Station Alpha uses your desktops Y resolution to write this value, so if a friend
|
||||
with a large monitor and a high screen resolution gives you an edited script,
|
||||
you can mess everything up by saving the script in SSA with your low-cost monitor.</p>
|
||||
|
||||
<p>The second, “[V4 Styles]”, is a list of style definitions. A style describe how will look
|
||||
a text on the screen. It defines font, font size, primary/…/outile colour, position, alignment, etc.</p>
|
||||
|
||||
<p>For example this:</p>
|
||||
|
||||
<pre><code class="language-ssa">Format: Name, Fontname, Fontsize, PrimaryColour, SecondaryColour, \
|
||||
TertiaryColour, BackColour, Bold, Italic, BorderStyle, Outline, \
|
||||
Shadow, Alignment, MarginL, MarginR, MarginV, AlphaLevel, Encoding
|
||||
Style: Wolf main,Wolf_Rain,56,15724527,15724527,15724527,4144959,0,\
|
||||
0,1,1,2,2,5,5,30,0,0
|
||||
</code></pre>
|
||||
|
||||
<p>The third, “[Events]”, is the list of text you want to display at the right timing.
|
||||
You can specify some attribute here. Like the style to use for this event
|
||||
(<strong>MUST</strong>be defined in the list), the position of the text (Left, Right, Vertical Margin),
|
||||
an effect. Name is mostly used by translator to know who said this sentence.
|
||||
Timing is in h:mm:ss.cc (centisec).</p>
|
||||
|
||||
<pre><code class="language-ssa">Format: Marked, Start, End, Style, Name, MarginL, MarginR, MarginV, \
|
||||
Effect, Text
|
||||
Dialogue: Marked=0,0:02:40.65,0:02:41.79,Wolf main,Cher,0000,0000,\
|
||||
0000,,Et les enregistrements de ses ondes delta ?
|
||||
Dialogue: Marked=0,0:02:42.42,0:02:44.15,Wolf main,autre,0000,0000,\
|
||||
0000,,Toujours rien.
|
||||
</code></pre>
|
||||
|
||||
<p>“[Pictures]” or “[Fonts]” part can be found in some SSA file, they contains UUE-encoded
|
||||
pictures/font but those features are only used by Sub Station Alpha – i.e.
|
||||
no filter (Vobsub/Avery Lee Subtiler filter) use them.</p>
|
||||
|
||||
<p>Now, how are they stored in Matroska?</p>
|
||||
|
||||
<ul>
|
||||
<li>All text is converted to UTF-8</li>
|
||||
<li>All the headers are stored in CodecPrivate
|
||||
(Script Info and the Styles list)</li>
|
||||
<li>Start & End field are used to set TimeStamp
|
||||
and the BlockDuration element. the data stored is:</li>
|
||||
<li>Events are stored in the Block
|
||||
in this order: ReadOrder, Layer, Style, Name, MarginL, MarginR, MarginV, Effect,
|
||||
Text (Layer comes from ASS specs … it’s empty for SSA.) “ReadOrder field is needed
|
||||
for the decoder to be able to reorder the streamed samples as they were placed originally in the file.”</li>
|
||||
</ul>
|
||||
|
||||
<p>Here is an example of an SSA file.</p>
|
||||
|
||||
<pre><code class="language-ssa">[Script Info]
|
||||
; This is a Sub Station Alpha v4 script.
|
||||
; For Sub Station Alpha info and downloads,
|
||||
; go to \
|
||||
; [http://www.eswat.demon.co.uk/](http://www.eswat.demon.co.uk/)
|
||||
; or email \
|
||||
; [kotus@eswat.demon.co.uk](mailto:kotus@eswat.demon.co.uk)
|
||||
Title: Wolf's rain 2
|
||||
Original Script: Anime-spirit Ishin-francais
|
||||
Original Translation: Coolman
|
||||
Original Editing: Spikewolfwood
|
||||
Original Timing: Lord_alucard
|
||||
Original Script Checking: Spikewolfwood
|
||||
ScriptType: v4.00
|
||||
Collisions: Normal
|
||||
PlayResY: 1024
|
||||
PlayDepth: 0
|
||||
Wav: 0, 128697,D:\Alex\Anime\- Fansub -\- TAFF -\WR_-_02_Wav.wav
|
||||
Wav: 0, 120692,H:\team truc\WR_-_02.wav
|
||||
Wav: 0, 116504,E:\sub\wolf's_rain\WOLF'S RAIN 02.wav
|
||||
LastWav: 3
|
||||
Timer: 100,0000
|
||||
|
||||
[V4 Styles]
|
||||
Format: Name, Fontname, Fontsize, PrimaryColour, SecondaryColour, \
|
||||
TertiaryColour, BackColour, Bold, Italic, BorderStyle, Outline, \
|
||||
Shadow, Alignment, MarginL, MarginR, MarginV, AlphaLevel, Encoding
|
||||
Style: Default,Arial,20,65535,65535,65535,-2147483640,-1,0,1,3,0,2,\
|
||||
30,30,30,0,0
|
||||
Style: Titre_episode,Akbar,140,15724527,65535,65535,986895,-1,0,1,1,\
|
||||
0,3,30,30,30,0,0
|
||||
Style: Wolf main,Wolf_Rain,56,15724527,15724527,15724527,4144959,0,\
|
||||
0,1,1,2,2,5,5,30,0,0
|
||||
|
||||
[Events]
|
||||
Format: Marked, Start, End, Style, Name, MarginL, MarginR, MarginV, \
|
||||
Effect, Text
|
||||
Dialogue: Marked=0,0:02:40.65,0:02:41.79,Wolf main,Cher,0000,0000,\
|
||||
0000,,Et les enregistrements de ses ondes delta ?
|
||||
Dialogue: Marked=0,0:02:42.42,0:02:44.15,Wolf main,autre,0000,0000,\
|
||||
0000,,Toujours rien.
|
||||
</code></pre>
|
||||
|
||||
<p>Here is what would be placed into the CodecPrivate element.</p>
|
||||
|
||||
<pre><code class="language-ssa">[Script Info]
|
||||
; This is a Sub Station Alpha v4 script.
|
||||
; For Sub Station Alpha info and downloads,
|
||||
; go to \
|
||||
; [http://www.eswat.demon.co.uk/](http://www.eswat.demon.co.uk/)
|
||||
; or email \
|
||||
; [kotus@eswat.demon.co.uk](mailto:kotus@eswat.demon.co.uk)
|
||||
Title: Wolf's rain 2
|
||||
Original Script: Anime-spirit Ishin-francais
|
||||
Original Translation: Coolman
|
||||
Original Editing: Spikewolfwood
|
||||
Original Timing: Lord_alucard
|
||||
Original Script Checking: Spikewolfwood
|
||||
ScriptType: v4.00
|
||||
Collisions: Normal
|
||||
PlayResY: 1024
|
||||
PlayDepth: 0
|
||||
Wav: 0, 128697,D:\Alex\Anime\- Fansub -\- TAFF -\WR_-_02_Wav.wav
|
||||
Wav: 0, 120692,H:\team truc\WR_-_02.wav
|
||||
Wav: 0, 116504,E:\sub\wolf's_rain\WOLF'S RAIN 02.wav
|
||||
LastWav: 3
|
||||
Timer: 100,0000
|
||||
|
||||
[V4 Styles]
|
||||
Format: Name, Fontname, Fontsize, PrimaryColour, SecondaryColour, \
|
||||
TertiaryColour, BackColour, Bold, Italic, BorderStyle, Outline, \
|
||||
Shadow, Alignment, MarginL, MarginR, MarginV, AlphaLevel, Encoding
|
||||
Style: Default,Arial,20,65535,65535,65535,-2147483640,-1,0,1,3,0,2,\
|
||||
30,30,30,0,0
|
||||
Style: Titre_episode,Akbar,140,15724527,65535,65535,986895,-1,0,1,1,\
|
||||
0,3,30,30,30,0,0
|
||||
Style: Wolf main,Wolf_Rain,56,15724527,15724527,15724527,4144959,0,\
|
||||
0,1,1,2,2,5,5,30,0,0
|
||||
</code></pre>
|
||||
|
||||
<p>And here are the two blocks that would be generated.</p>
|
||||
|
||||
<p>Block’s timestamp: 00:02:40.650
|
||||
BlockDuration: 00:00:01.140</p>
|
||||
|
||||
<pre><code class="language-ssa">1,,Wolf main,Cher,0000,0000,0000,,Et les enregistrements de ses \
|
||||
ondes delta ?
|
||||
</code></pre>
|
||||
|
||||
<p>Block’s timestamp: 00:02:42.420
|
||||
BlockDuration: 00:00:01.730</p>
|
||||
|
||||
<pre><code class="language-ssa">2,,Wolf main,autre,0000,0000,0000,,Toujours rien.
|
||||
</code></pre>
|
||||
|
||||
<h2 id="webvtt">WebVTT</h2>
|
||||
|
||||
<p>The “Web Video Text Tracks Format” (short: WebVTT) is developed by the <a href="https://www.w3.org/">World Wide Web Consortium (W3C)</a>.
|
||||
Its specifications are <a href="https://w3c.github.io/webvtt/">freely available</a>.</p>
|
||||
|
||||
<p>The guiding principles for the storage of WebVTT in Matroska are:</p>
|
||||
|
||||
<ul>
|
||||
<li>Consistency: store data in a similar way to other subtitle codecs</li>
|
||||
<li>Simplicity: making decoding and remuxing as easy as possible for existing infrastructures</li>
|
||||
<li>Completeness: keeping as much data as possible from the original WebVTT file</li>
|
||||
</ul>
|
||||
|
||||
<h3 id="storage-of-webvtt-in-matroska">Storage of WebVTT in Matroska</h3>
|
||||
|
||||
<h4 id="codecid-codec-identification">CodecID: codec identification</h4>
|
||||
|
||||
<p>The CodecID to use is <code class="language-plaintext highlighter-rouge">S_TEXT/WEBVTT</code>.</p>
|
||||
|
||||
<h4 id="codecprivate-storage-of-global-webvtt-blocks">CodecPrivate: storage of global WebVTT blocks</h4>
|
||||
|
||||
<p>This element contains all global blocks before the first subtitle entry. This starts at the “<code class="language-plaintext highlighter-rouge">WEBVTT</code>”
|
||||
file identification marker but excludes the optional byte order mark.</p>
|
||||
|
||||
<h4 id="storage-of-non-global-webvtt-blocks">Storage of non-global WebVTT blocks</h4>
|
||||
|
||||
<p>Non-global WebVTT blocks (e.g., “NOTE”) before a WebVTT Cue Text are stored in Matroska’s BlockAddition
|
||||
element together with the Matroska Block containing the WebVTT Cue Text these blocks precede
|
||||
(see below for the actual format).</p>
|
||||
|
||||
<h4 id="storage-of-cues-in-matroska-blocks">Storage of Cues in Matroska blocks</h4>
|
||||
|
||||
<p>Each WebVTT Cue Text is stored directly in the Matroska Block.</p>
|
||||
|
||||
<p>A muxer <strong>MUST</strong> change all WebVTT Cue Timestamps present within the Cue Text to be relative
|
||||
to the Matroska Block’s timestamp.</p>
|
||||
|
||||
<p>The Cue’s start timestamp is used as the Matroska Block’s timestamp.</p>
|
||||
|
||||
<p>The difference between the Cue’s end timestamp and its start timestamp is used as
|
||||
the Matroska Block’s duration.</p>
|
||||
|
||||
<h4 id="blockadditions-storing-non-global-webvtt-blocks-cue-settings-lists-and-cue-identifiers">BlockAdditions: storing non-global WebVTT blocks, Cue Settings Lists and Cue identifiers</h4>
|
||||
|
||||
<p>Each Matroska Block may be accompanied by one BlockAdditions element. Its format is as follows:</p>
|
||||
|
||||
<ol>
|
||||
<li>The first line contains the WebVTT Cue Text’s optional Cue Settings List followed by
|
||||
one line feed character (U+0x000a). The Cue Settings List may be empty, in which case
|
||||
the line consists of the line feed character only.</li>
|
||||
<li>The second line contains the WebVTT Cue Text’s optional Cue Identifier followed by
|
||||
one line feed character (U+0x000a). The line may be empty indicating that there was
|
||||
no Cue Identifier in the source file, in which case the line consists of the line feed character only.</li>
|
||||
<li>The third and all following lines contain all WebVTT Comment Blocks that precede
|
||||
the current WebVTT Cue Block. These may be absent.</li>
|
||||
</ol>
|
||||
|
||||
<p>If there is no Matroska BlockAddition element stored together with the Matroska Block,
|
||||
then all three components (Cue Settings List, Cue Identifier, Cue Comments) <strong>MUST</strong> be assumed to be absent.</p>
|
||||
|
||||
<h3 id="examples-of-transformation">Examples of transformation</h3>
|
||||
|
||||
<p>Here’s an example how a WebVTT is transformed.</p>
|
||||
|
||||
<h4 id="example-webvtt-file">Example WebVTT file</h4>
|
||||
|
||||
<p>Let’s take the following example file:</p>
|
||||
|
||||
<pre><code class="language-webvtt">WEBVTT with text after the signature
|
||||
|
||||
STYLE
|
||||
::cue {
|
||||
background-image: linear-gradient(to bottom, dimgray, lightgray);
|
||||
color: papayawhip;
|
||||
}
|
||||
/* Style blocks cannot use blank lines nor "dash dash greater \
|
||||
than" */
|
||||
|
||||
NOTE comment blocks can be used between style blocks.
|
||||
|
||||
STYLE
|
||||
::cue(b) {
|
||||
color: peachpuff;
|
||||
}
|
||||
|
||||
REGION
|
||||
id:bill
|
||||
width:40%
|
||||
lines:3
|
||||
regionanchor:0%,100%
|
||||
viewportanchor:10%,90%
|
||||
scroll:up
|
||||
|
||||
NOTE
|
||||
Notes always span a whole block and can cover multiple
|
||||
lines. Like this one.
|
||||
An empty line ends the block.
|
||||
|
||||
hello
|
||||
00:00:00.000 --> 00:00:10.000
|
||||
Example entry 1: Hello <b>world</b>.
|
||||
|
||||
NOTE style blocks cannot appear after the first cue.
|
||||
|
||||
00:00:25.000 --> 00:00:35.000
|
||||
Example entry 2: Another entry.
|
||||
This one has multiple lines.
|
||||
|
||||
00:01:03.000 --> 00:01:06.500 position:90% align:right size:35%
|
||||
Example entry 3: That stuff to the right of the timestamps are cue \
|
||||
settings.
|
||||
|
||||
00:03:10.000 --> 00:03:20.000
|
||||
Example entry 4: Entries can even include timestamps.
|
||||
For example:<00:03:15.000>This becomes visible five seconds
|
||||
after the first part.
|
||||
</code></pre>
|
||||
|
||||
<h4 id="example-of-codecprivate">Example of CodecPrivate</h4>
|
||||
|
||||
<p>The resulting CodecPrivate element will look like this:</p>
|
||||
|
||||
<pre><code class="language-webvtt">WEBVTT with text after the signature
|
||||
|
||||
STYLE
|
||||
::cue {
|
||||
background-image: linear-gradient(to bottom, dimgray, lightgray);
|
||||
color: papayawhip;
|
||||
}
|
||||
/* Style blocks cannot use blank lines nor "dash dash greater \
|
||||
than" */
|
||||
|
||||
NOTE comment blocks can be used between style blocks.
|
||||
|
||||
STYLE
|
||||
::cue(b) {
|
||||
color: peachpuff;
|
||||
}
|
||||
|
||||
REGION
|
||||
id:bill
|
||||
width:40%
|
||||
lines:3
|
||||
regionanchor:0%,100%
|
||||
viewportanchor:10%,90%
|
||||
scroll:up
|
||||
|
||||
NOTE
|
||||
Notes always span a whole block and can cover multiple
|
||||
lines. Like this one.
|
||||
An empty line ends the block.
|
||||
</code></pre>
|
||||
|
||||
<h4 id="storage-of-cue-1">Storage of Cue 1</h4>
|
||||
|
||||
<p>Example Cue 1: timestamp 00:00:00.000, duration 00:00:10.000, Block’s content:</p>
|
||||
|
||||
<pre><code class="language-webvtt">Example entry 1: Hello <b>world</b>.
|
||||
</code></pre>
|
||||
|
||||
<p>BlockAddition’s content starts with one empty line as there’s no Cue Settings List:</p>
|
||||
|
||||
<pre><code class="language-webvtt">
|
||||
hello
|
||||
</code></pre>
|
||||
|
||||
<h4 id="storage-of-cue-2">Storage of Cue 2</h4>
|
||||
|
||||
<p>Example Cue 2: timestamp 00:00:25.000, duration 00:00:10.000, Block’s content:</p>
|
||||
|
||||
<pre><code class="language-webvtt">Example entry 2: Another entry.
|
||||
This one has multiple lines.
|
||||
</code></pre>
|
||||
|
||||
<p>BlockAddition’s content starts with two empty lines as there’s neither a Cue Settings List nor a Cue Identifier:</p>
|
||||
|
||||
<pre><code class="language-webvtt">
|
||||
NOTE style blocks cannot appear after the first cue.
|
||||
</code></pre>
|
||||
|
||||
<h4 id="storage-of-cue-3">Storage of Cue 3</h4>
|
||||
|
||||
<p>Example Cue 3: timestamp 00:01:03.000, duration 00:00:03.500, Block’s content:</p>
|
||||
|
||||
<pre><code class="language-webvtt">Example entry 3: That stuff to the right of the timestamps are cue \
|
||||
settings.
|
||||
</code></pre>
|
||||
|
||||
<p>BlockAddition’s content ends with an empty line as there’s no Cue Identifier and
|
||||
there were no WebVTT Comment blocks:</p>
|
||||
|
||||
<pre><code class="language-webvtt">position:90% align:right size:35%
|
||||
|
||||
</code></pre>
|
||||
|
||||
<h4 id="storage-of-cue-4">Storage of Cue 4</h4>
|
||||
|
||||
<p>Example Cue 4: timestamp 00:03:10.000, duration 00:00:10.000, Block’s content:</p>
|
||||
|
||||
<p>Example entry 4: Entries can even include timestamps. For
|
||||
example:<00:00:05.000>This becomes visible five seconds after the
|
||||
first part.</p>
|
||||
|
||||
<p>This Block does not need a BlockAddition as the Cue did not contain an Identifier,
|
||||
nor a Settings List, and it wasn’t preceded by Comment blocks.</p>
|
||||
|
||||
<h3 id="storage-of-webvtt-in-matroska-vs-webm">Storage of WebVTT in Matroska vs. WebM</h3>
|
||||
|
||||
<p>Note: the storage of WebVTT in Matroska is not the same as the design document for storage
|
||||
of WebVTT in WebM. There are several reasons for this including but not limited to:
|
||||
the WebM document is old (from February 2012) and was based on an earlier draft of WebVTT
|
||||
and ignores several parts that were added to WebVTT later; WebM does still <a href="http://www.webmproject.org/docs/container/">not support subtitles at all</a>;
|
||||
the proposal suggests splitting the information across multiple tracks making
|
||||
demuxer’s and remuxer’s life very difficult.</p>
|
||||
|
||||
<h2 id="hdmv-presentation-graphics-subtitles">HDMV presentation graphics subtitles</h2>
|
||||
|
||||
<p>The specifications for the HDMV presentation graphics subtitle format (short: HDMV PGS)
|
||||
can be found in the document “Blu-ray Disc Read-Only Format; Part 3 — Audio Visual Basic Specifications”
|
||||
in section 9.14 “HDMV graphics streams”.</p>
|
||||
|
||||
<h3 id="storage-of-hdmv-presentation-graphics-subtitles">Storage of HDMV presentation graphics subtitles</h3>
|
||||
|
||||
<p>The CodecID to use is <code class="language-plaintext highlighter-rouge">S_HDMV/PGS</code>. A CodecPrivate element is not used.</p>
|
||||
|
||||
<h4 id="storage-of-hdmv-pgs-segments-in-matroska-blocks">Storage of HDMV PGS Segments in Matroska Blocks</h4>
|
||||
|
||||
<p>Each HDMV PGS Segment (short: Segment) will be stored in a Matroska Block.
|
||||
A Segment is the data structure described in section 9.14.2.1 “Segment coding structure and parameters”
|
||||
of the Blu-ray specifications.</p>
|
||||
|
||||
<p>Each Segment contains a presentation timestamp. This timestamp will be used as
|
||||
the timestamp for the Matroska Block.</p>
|
||||
|
||||
<p>A Segment is normally shown until a subsequent Segment is encountered. Therefore the Matroska Block
|
||||
<strong>MAY</strong> have no Duration. In that case, a player <strong>MUST</strong> display a Segment within a Matroska Block
|
||||
until the next Segment is encountered.</p>
|
||||
|
||||
<p>A muxer <strong>MAY</strong> use a Duration, e.g., by calculating the distance between two subsequent Segments.
|
||||
If a Matroska Block has a Duration, a player <strong>MUST</strong> display that Segment only for
|
||||
the duration of the Block’s Duration.</p>
|
||||
|
||||
<h2 id="hdmv-text-subtitles">HDMV text subtitles</h2>
|
||||
|
||||
<p>The specifications for the HDMV text subtitle format (short: HDMV
|
||||
TextST) can be found
|
||||
in the document “Blu-ray Disc Read-Only Format; Part 3 — Audio Visual
|
||||
Basic Specifications” in section 9.15 “HDMV text subtitle streams”.</p>
|
||||
|
||||
<h3 id="storage-of-hdmv-text-subtitles">Storage of HDMV text subtitles</h3>
|
||||
|
||||
<p>The CodecID to use is <code class="language-plaintext highlighter-rouge">S_HDMV/TEXTST</code>.</p>
|
||||
|
||||
<p>A CodecPrivate Element is required. It <strong>MUST</strong> contain the stream’s Dialog Style Segment
|
||||
as described in section 9.15.4.2 “Dialog Style Segment” of the Blu-ray specifications.</p>
|
||||
|
||||
<h4 id="storage-of-hdmv-textst-dialog-presentation-segments-in-matroska-blocks">Storage of HDMV TextST Dialog Presentation Segments in Matroska Blocks</h4>
|
||||
|
||||
<p>Each HDMV Dialog Presentation Segment (short: Segment) will be stored in a Matroska Block.
|
||||
A Segment is the data structure described in section 9.15.4.3 “Dialog presentation segment”
|
||||
of the Blu-ray specifications.</p>
|
||||
|
||||
<p>Each Segment contains a start and an end presentation timestamp (short: start PTS & end PTS).
|
||||
The start PTS will be used as the timestamp for the Matroska Block. The Matroska Block <strong>MUST</strong>
|
||||
have a Duration, and that Duration is the difference between the end PTS and the start PTS.</p>
|
||||
|
||||
<p>A player <strong>MUST</strong> use the Matroska Block’s timestamp and Duration instead of the Segment’s
|
||||
start and end PTS for determining when and how long to show the Segment.</p>
|
||||
|
||||
<h4 id="character-set">Character set</h4>
|
||||
|
||||
<p>When TextST subtitles are stored inside Matroska, the only allowed character set is UTF-8.</p>
|
||||
|
||||
<p>Each HDMV text subtitle stream in a Blu-ray can use one of a handful of character sets.
|
||||
This information is not stored in the MPEG2 Transport Stream itself but in the accompanying Clip Information file.</p>
|
||||
|
||||
<p>Therefore a muxer <strong>MUST</strong> parse the accompanying Clip Information file. If the information
|
||||
indicates a character set other than UTF-8, it <strong>MUST</strong> re-encode all text Dialog Presentation Segments
|
||||
from the indicated character set to UTF-8 prior to storing them in Matroska.</p>
|
||||
|
||||
<h2 id="digital-video-broadcasting-dvb-subtitles">Digital Video Broadcasting (DVB) subtitles</h2>
|
||||
|
||||
<p>The specifications for the Digital Video Broadcasting subtitle bitstream format (short: DVB subtitles)
|
||||
can be found in the document “ETSI EN 300 743 - Digital Video Broadcasting (DVB); Subtitling systems”.
|
||||
The storage of DVB subtitles in MPEG transport streams is specified in the document
|
||||
“ETSI EN 300 468 - Digital Video Broadcasting (DVB); Specification for Service Information (SI) in DVB systems”.</p>
|
||||
|
||||
<h3 id="storage-of-dvb-subtitles">Storage of DVB subtitles</h3>
|
||||
|
||||
<h4 id="codecid">CodecID</h4>
|
||||
|
||||
<p>The CodecID to use is <code class="language-plaintext highlighter-rouge">S_DVBSUB</code>.</p>
|
||||
|
||||
<h4 id="codecprivate">CodecPrivate</h4>
|
||||
|
||||
<p>The CodecPrivate element is five bytes long and has the following structure:</p>
|
||||
|
||||
<ul>
|
||||
<li>2 bytes: composition page ID (bit string, left bit first)</li>
|
||||
<li>2 bytes: ancillary page ID (bit string, left bit first)</li>
|
||||
<li>1 byte: subtitling type (bit string, left bit first)</li>
|
||||
</ul>
|
||||
|
||||
<p>The semantics of these bytes are the same as the ones described in
|
||||
section 6.2.41 “Subtitling descriptor” of ETSI EN 300 468.</p>
|
||||
|
||||
<h4 id="storage-of-dvb-subtitles-in-matroska-blocks">Storage of DVB subtitles in Matroska Blocks</h4>
|
||||
|
||||
<p>Each Matroska Block consists of one or more DVB Subtitle Segments as described
|
||||
in segment 7.2 “Syntax and semantics of the subtitling segment” of ETSI EN 300 743.</p>
|
||||
|
||||
<p>Each Matroska Block <strong>SHOULD</strong> have a Duration indicating how long the DVB Subtitle Segments
|
||||
in that Block <strong>SHOULD</strong> be displayed.</p>
|
||||
|
||||
<h2 id="arib-isdb-subtitles">ARIB (ISDB) subtitles</h2>
|
||||
|
||||
<p>The specifications for the ARIB B-24 subtitle bitstream format (short: ARIB subtitles)
|
||||
and its storage in MPEG transport streams can be found in the documents
|
||||
[@!ARIB.STD-B24], [@!ARIB.STD-B10], and [@!ARIB.TR-B14].</p>
|
||||
|
||||
<h3 id="storage-of-arib-subtitles">Storage of ARIB subtitles</h3>
|
||||
|
||||
<h4 id="codecid-1">CodecID</h4>
|
||||
|
||||
<p>The CodecID to use is <code class="language-plaintext highlighter-rouge">S_ARIBSUB</code>.</p>
|
||||
|
||||
<h4 id="codecprivate-1">CodecPrivate</h4>
|
||||
|
||||
<p>The CodecPrivate element is three bytes long and has the following structure:</p>
|
||||
|
||||
<ul>
|
||||
<li>1 byte: component tag (bit string, left bit first)</li>
|
||||
<li>2 bytes: data component ID (bit string, left bit first)</li>
|
||||
</ul>
|
||||
|
||||
<p>The semantics of the component tag are the same as those described in
|
||||
[@!ARIB.STD-B10], part 2, Annex J.
|
||||
The semantics of the data component ID are the same as those described
|
||||
in [@!ARIB.TR-B14], fascicle 2, Vol. 3, Section 2, 4.2.8.1.</p>
|
||||
|
||||
<h4 id="storage-of-arib-subtitles-in-matroska-blocks">Storage of ARIB subtitles in Matroska Blocks</h4>
|
||||
|
||||
<p>Each Matroska Block consists of a single synchronized PES data structure as described in
|
||||
chapter 5 “Independent PES transmission protocol” of [@!ARIB.STD-B24], volume 3, with a
|
||||
Synchronized_PES_data_byte block containing one or more ISDB Caption Data Groups as described
|
||||
in chapter 9 “Transmission of caption and superimpose” of [@!ARIB.STD-B24], volume 1, part 3.
|
||||
All of the Caption Statement Data Groups in a given Matroska Track <strong>MUST</strong> use the same language index.</p>
|
||||
|
||||
<p>A Data Group is normally shown until a subsequent Group provides instructions to clear it.
|
||||
Therefore the Matroska Block <strong>SHOULD NOT</strong> have a Duration.
|
||||
A player <strong>SHOULD</strong> display a Data Group within a Matroska Block until its internal duration elapses,
|
||||
or until a subsequent Data Group removes it.</p>
|
||||
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<footer id="footer" class="site-footer region region-footer">
|
||||
<div id="block-block-1" class="block block-block first last odd">
|
||||
<p class="rtecenter" style="font-size: smaller">
|
||||
<b>Copyright ® 2005 - 2020 Matroska (non-profit org), All Rights Reserved.</b>
|
||||
|
|
||||
<a href="https://www.matroska.org/imprint.html">Imprint/Impressum</a>
|
||||
|
|
||||
<a href="https://www.matroska.org/data_protection_policy.html">Data Protection Policy/Datenschutzerklärung</a>
|
||||
</p>
|
||||
</div>
|
||||
</footer>
|
||||
|
||||
|
||||
|
||||
|
||||
</body><script src="Subtitles_files/passkeys.js"></script></html>
|
||||
670
documentation/Subtitles_files/main.css
Normal file
670
documentation/Subtitles_files/main.css
Normal file
@@ -0,0 +1,670 @@
|
||||
/**
|
||||
* Reset some basic elements
|
||||
*/
|
||||
body, h1, h2, h3, h4, h5, h6,
|
||||
p, blockquote, pre, hr,
|
||||
dl, dd, ol, ul, figure {
|
||||
margin: 0;
|
||||
padding: 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* Basic styling
|
||||
*/
|
||||
body {
|
||||
font-family: Helvetica, Arial, sans-serif;
|
||||
font-size: 16px;
|
||||
line-height: 1.5;
|
||||
color: #111;
|
||||
background-color: #fdfdfd;
|
||||
-webkit-text-size-adjust: 100%;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set `margin-bottom` to maintain vertical rhythm
|
||||
*/
|
||||
h1, h2, h3, h4, h5, h6,
|
||||
p, blockquote, pre,
|
||||
ul, ol, dl, figure,
|
||||
.highlight {
|
||||
margin-bottom: 15px;
|
||||
}
|
||||
|
||||
/**
|
||||
* Images
|
||||
*/
|
||||
img {
|
||||
max-width: 100%;
|
||||
vertical-align: middle;
|
||||
}
|
||||
|
||||
/**
|
||||
* Figures
|
||||
*/
|
||||
figure > img {
|
||||
display: block;
|
||||
}
|
||||
|
||||
figcaption {
|
||||
font-size: 14px;
|
||||
}
|
||||
|
||||
/**
|
||||
* Lists
|
||||
*/
|
||||
ul, ol {
|
||||
margin-left: 30px;
|
||||
}
|
||||
|
||||
li > ul,
|
||||
li > ol {
|
||||
margin-bottom: 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* Headings
|
||||
*/
|
||||
h1, h2, h3, h4, h5, h6 {
|
||||
font-weight: 300;
|
||||
}
|
||||
|
||||
/**
|
||||
* Links
|
||||
*/
|
||||
a {
|
||||
color: #2a7ae2;
|
||||
text-decoration: none;
|
||||
}
|
||||
a:visited {
|
||||
color: #1756a9;
|
||||
}
|
||||
a:hover {
|
||||
color: #111;
|
||||
text-decoration: underline;
|
||||
}
|
||||
|
||||
/**
|
||||
* Blockquotes
|
||||
*/
|
||||
blockquote {
|
||||
color: #828282;
|
||||
border-left: 4px solid #e8e8e8;
|
||||
padding-left: 15px;
|
||||
font-size: 18px;
|
||||
letter-spacing: -1px;
|
||||
font-style: italic;
|
||||
}
|
||||
blockquote > :last-child {
|
||||
margin-bottom: 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* Code formatting
|
||||
*/
|
||||
pre,
|
||||
code {
|
||||
font-size: 15px;
|
||||
border: 1px solid #e8e8e8;
|
||||
border-radius: 3px;
|
||||
background-color: #eef;
|
||||
}
|
||||
|
||||
code {
|
||||
padding: 1px 5px;
|
||||
}
|
||||
|
||||
pre {
|
||||
padding: 8px 12px;
|
||||
overflow-x: scroll;
|
||||
}
|
||||
pre > code {
|
||||
border: 0;
|
||||
padding-right: 0;
|
||||
padding-left: 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* Wrapper
|
||||
*/
|
||||
.wrapper {
|
||||
max-width: -webkit-calc(1600px - (30px * 2));
|
||||
max-width: calc(1600px - (30px * 2));
|
||||
margin-right: auto;
|
||||
margin-left: auto;
|
||||
padding-right: 30px;
|
||||
padding-left: 30px;
|
||||
}
|
||||
@media screen and (max-width: 800px) {
|
||||
.wrapper {
|
||||
max-width: -webkit-calc(1600px - (30px));
|
||||
max-width: calc(1600px - (30px));
|
||||
padding-right: 15px;
|
||||
padding-left: 15px;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Clearfix
|
||||
*/
|
||||
.footer-col-wrapper:after, .wrapper:after {
|
||||
content: "";
|
||||
display: table;
|
||||
clear: both;
|
||||
}
|
||||
|
||||
/**
|
||||
* Icons
|
||||
*/
|
||||
.icon > svg {
|
||||
display: inline-block;
|
||||
width: 16px;
|
||||
height: 16px;
|
||||
vertical-align: middle;
|
||||
}
|
||||
.icon > svg path {
|
||||
fill: #828282;
|
||||
}
|
||||
|
||||
/**
|
||||
* Other general Matroska stuff
|
||||
*/
|
||||
table {
|
||||
border: 1px solid black;
|
||||
border-collapse: collapse;
|
||||
}
|
||||
|
||||
thead th {
|
||||
border: 1px solid black;
|
||||
padding: 1px 3px;
|
||||
}
|
||||
|
||||
tbody td {
|
||||
border: 1px solid black;
|
||||
padding: 1px 3px;
|
||||
}
|
||||
|
||||
/**
|
||||
* Matroska specification table
|
||||
*/
|
||||
.techdef table {
|
||||
font-family: sans-serif;
|
||||
background: #fff;
|
||||
margin: 0;
|
||||
padding: 0;
|
||||
}
|
||||
|
||||
.techdef th {
|
||||
font-size: larger;
|
||||
border: 5px solid #ddd;
|
||||
background: #eee;
|
||||
padding: 0.5em 0 0.5em 0;
|
||||
margin: 0;
|
||||
}
|
||||
|
||||
.techdef tr {
|
||||
margin: 0;
|
||||
padding: 0;
|
||||
}
|
||||
|
||||
.techdef td {
|
||||
margin: 0;
|
||||
border: 1px solid #eee;
|
||||
padding: 2px;
|
||||
}
|
||||
|
||||
.techdef .level0 {
|
||||
background: #fff;
|
||||
}
|
||||
|
||||
.techdef .level1 {
|
||||
background: #eff;
|
||||
}
|
||||
|
||||
.techdef .level2 {
|
||||
background: #eef;
|
||||
}
|
||||
|
||||
.techdef .level3 {
|
||||
background: #dde;
|
||||
}
|
||||
|
||||
.techdef .level4 {
|
||||
background: #ccd;
|
||||
}
|
||||
|
||||
.techdef .level5 {
|
||||
background: #bbc;
|
||||
}
|
||||
|
||||
.techdef .level6 {
|
||||
background: #aab;
|
||||
}
|
||||
|
||||
.techdef .level7 {
|
||||
background: #99a;
|
||||
}
|
||||
|
||||
.techdef .level8 {
|
||||
background: #889;
|
||||
}
|
||||
|
||||
.version2 {
|
||||
color: #aaa;
|
||||
background: #eee;
|
||||
}
|
||||
|
||||
/**
|
||||
* Site header
|
||||
*/
|
||||
.site-header {
|
||||
border-bottom: 2px solid #b4d7f0;
|
||||
padding-bottom: 10px;
|
||||
min-height: 56px;
|
||||
position: relative;
|
||||
}
|
||||
|
||||
.site-title {
|
||||
font-size: 26px;
|
||||
line-height: 56px;
|
||||
letter-spacing: -1px;
|
||||
margin-bottom: 0;
|
||||
float: left;
|
||||
}
|
||||
.site-title, .site-title:visited {
|
||||
color: #424242;
|
||||
}
|
||||
|
||||
.site-nav {
|
||||
float: right;
|
||||
line-height: 56px;
|
||||
}
|
||||
.site-nav .menu-icon {
|
||||
display: none;
|
||||
}
|
||||
.site-nav .page-link {
|
||||
color: #111;
|
||||
line-height: 1.5;
|
||||
}
|
||||
.site-nav .page-link:not(:first-child) {
|
||||
margin-left: 20px;
|
||||
}
|
||||
@media screen and (max-width: 600px) {
|
||||
.site-nav {
|
||||
position: absolute;
|
||||
top: 9px;
|
||||
right: 30px;
|
||||
background-color: #fdfdfd;
|
||||
border: 1px solid #e8e8e8;
|
||||
border-radius: 5px;
|
||||
text-align: right;
|
||||
}
|
||||
.site-nav .menu-icon {
|
||||
display: block;
|
||||
float: right;
|
||||
width: 36px;
|
||||
height: 26px;
|
||||
line-height: 0;
|
||||
padding-top: 10px;
|
||||
text-align: center;
|
||||
}
|
||||
.site-nav .menu-icon > svg {
|
||||
width: 18px;
|
||||
height: 15px;
|
||||
}
|
||||
.site-nav .menu-icon > svg path {
|
||||
fill: #424242;
|
||||
}
|
||||
.site-nav .trigger {
|
||||
clear: both;
|
||||
display: none;
|
||||
}
|
||||
.site-nav:hover .trigger {
|
||||
display: block;
|
||||
padding-bottom: 5px;
|
||||
}
|
||||
.site-nav .page-link {
|
||||
display: block;
|
||||
padding: 5px 10px;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Site footer
|
||||
*/
|
||||
.site-footer {
|
||||
border-top: 2px solid #b4d7f0;
|
||||
padding: 30px 0;
|
||||
text-align: center;
|
||||
}
|
||||
|
||||
.footer-heading {
|
||||
font-size: 18px;
|
||||
margin-bottom: 15px;
|
||||
}
|
||||
|
||||
.contact-list,
|
||||
.social-media-list {
|
||||
list-style: none;
|
||||
margin-left: 0;
|
||||
}
|
||||
|
||||
.footer-col-wrapper {
|
||||
font-size: 15px;
|
||||
color: #828282;
|
||||
margin-left: -15px;
|
||||
}
|
||||
|
||||
.footer-col {
|
||||
float: left;
|
||||
margin-bottom: 15px;
|
||||
padding-left: 15px;
|
||||
}
|
||||
|
||||
.footer-col-1 {
|
||||
width: -webkit-calc(35% - (30px / 2));
|
||||
width: calc(35% - (30px / 2));
|
||||
}
|
||||
|
||||
.footer-col-2 {
|
||||
width: -webkit-calc(20% - (30px / 2));
|
||||
width: calc(20% - (30px / 2));
|
||||
}
|
||||
|
||||
.footer-col-3 {
|
||||
width: -webkit-calc(45% - (30px / 2));
|
||||
width: calc(45% - (30px / 2));
|
||||
}
|
||||
|
||||
@media screen and (max-width: 800px) {
|
||||
.footer-col-1,
|
||||
.footer-col-2 {
|
||||
width: -webkit-calc(50% - (30px / 2));
|
||||
width: calc(50% - (30px / 2));
|
||||
}
|
||||
.footer-col-3 {
|
||||
width: -webkit-calc(100% - (30px / 2));
|
||||
width: calc(100% - (30px / 2));
|
||||
}
|
||||
}
|
||||
@media screen and (max-width: 600px) {
|
||||
.footer-col {
|
||||
float: none;
|
||||
width: -webkit-calc(100% - (30px / 2));
|
||||
width: calc(100% - (30px / 2));
|
||||
}
|
||||
}
|
||||
/**
|
||||
* Page content
|
||||
*/
|
||||
.page-content {
|
||||
padding: 30px 0;
|
||||
}
|
||||
|
||||
.page-heading {
|
||||
font-size: 20px;
|
||||
}
|
||||
|
||||
.post-list {
|
||||
margin-left: 0;
|
||||
list-style: none;
|
||||
}
|
||||
.post-list > li {
|
||||
margin-bottom: 30px;
|
||||
}
|
||||
|
||||
.post-meta {
|
||||
font-size: 14px;
|
||||
color: #828282;
|
||||
}
|
||||
|
||||
.post-link {
|
||||
display: block;
|
||||
font-size: 24px;
|
||||
}
|
||||
|
||||
/**
|
||||
* Posts
|
||||
*/
|
||||
.post-header {
|
||||
margin-bottom: 30px;
|
||||
}
|
||||
|
||||
.post-title {
|
||||
font-size: 42px;
|
||||
letter-spacing: -1px;
|
||||
line-height: 1;
|
||||
}
|
||||
@media screen and (max-width: 800px) {
|
||||
.post-title {
|
||||
font-size: 36px;
|
||||
}
|
||||
}
|
||||
|
||||
.post-content {
|
||||
margin-bottom: 30px;
|
||||
}
|
||||
.post-content h2 {
|
||||
font-size: 32px;
|
||||
}
|
||||
@media screen and (max-width: 800px) {
|
||||
.post-content h2 {
|
||||
font-size: 28px;
|
||||
}
|
||||
}
|
||||
.post-content h3 {
|
||||
font-size: 26px;
|
||||
}
|
||||
@media screen and (max-width: 800px) {
|
||||
.post-content h3 {
|
||||
font-size: 22px;
|
||||
}
|
||||
}
|
||||
.post-content h4 {
|
||||
font-size: 20px;
|
||||
}
|
||||
@media screen and (max-width: 800px) {
|
||||
.post-content h4 {
|
||||
font-size: 18px;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Syntax highlighting styles
|
||||
*/
|
||||
.highlight {
|
||||
background: #fff;
|
||||
}
|
||||
.highlight .c {
|
||||
color: #998;
|
||||
font-style: italic;
|
||||
}
|
||||
.highlight .err {
|
||||
color: #a61717;
|
||||
background-color: #e3d2d2;
|
||||
}
|
||||
.highlight .k {
|
||||
font-weight: bold;
|
||||
}
|
||||
.highlight .o {
|
||||
font-weight: bold;
|
||||
}
|
||||
.highlight .cm {
|
||||
color: #998;
|
||||
font-style: italic;
|
||||
}
|
||||
.highlight .cp {
|
||||
color: #999;
|
||||
font-weight: bold;
|
||||
}
|
||||
.highlight .c1 {
|
||||
color: #998;
|
||||
font-style: italic;
|
||||
}
|
||||
.highlight .cs {
|
||||
color: #999;
|
||||
font-weight: bold;
|
||||
font-style: italic;
|
||||
}
|
||||
.highlight .gd {
|
||||
color: #000;
|
||||
background-color: #fdd;
|
||||
}
|
||||
.highlight .gd .x {
|
||||
color: #000;
|
||||
background-color: #faa;
|
||||
}
|
||||
.highlight .ge {
|
||||
font-style: italic;
|
||||
}
|
||||
.highlight .gr {
|
||||
color: #a00;
|
||||
}
|
||||
.highlight .gh {
|
||||
color: #999;
|
||||
}
|
||||
.highlight .gi {
|
||||
color: #000;
|
||||
background-color: #dfd;
|
||||
}
|
||||
.highlight .gi .x {
|
||||
color: #000;
|
||||
background-color: #afa;
|
||||
}
|
||||
.highlight .go {
|
||||
color: #888;
|
||||
}
|
||||
.highlight .gp {
|
||||
color: #555;
|
||||
}
|
||||
.highlight .gs {
|
||||
font-weight: bold;
|
||||
}
|
||||
.highlight .gu {
|
||||
color: #aaa;
|
||||
}
|
||||
.highlight .gt {
|
||||
color: #a00;
|
||||
}
|
||||
.highlight .kc {
|
||||
font-weight: bold;
|
||||
}
|
||||
.highlight .kd {
|
||||
font-weight: bold;
|
||||
}
|
||||
.highlight .kp {
|
||||
font-weight: bold;
|
||||
}
|
||||
.highlight .kr {
|
||||
font-weight: bold;
|
||||
}
|
||||
.highlight .kt {
|
||||
color: #458;
|
||||
font-weight: bold;
|
||||
}
|
||||
.highlight .m {
|
||||
color: #099;
|
||||
}
|
||||
.highlight .s {
|
||||
color: #d14;
|
||||
}
|
||||
.highlight .na {
|
||||
color: #008080;
|
||||
}
|
||||
.highlight .nb {
|
||||
color: #0086B3;
|
||||
}
|
||||
.highlight .nc {
|
||||
color: #458;
|
||||
font-weight: bold;
|
||||
}
|
||||
.highlight .no {
|
||||
color: #008080;
|
||||
}
|
||||
.highlight .ni {
|
||||
color: #800080;
|
||||
}
|
||||
.highlight .ne {
|
||||
color: #900;
|
||||
font-weight: bold;
|
||||
}
|
||||
.highlight .nf {
|
||||
color: #900;
|
||||
font-weight: bold;
|
||||
}
|
||||
.highlight .nn {
|
||||
color: #555;
|
||||
}
|
||||
.highlight .nt {
|
||||
color: #000080;
|
||||
}
|
||||
.highlight .nv {
|
||||
color: #008080;
|
||||
}
|
||||
.highlight .ow {
|
||||
font-weight: bold;
|
||||
}
|
||||
.highlight .w {
|
||||
color: #bbb;
|
||||
}
|
||||
.highlight .mf {
|
||||
color: #099;
|
||||
}
|
||||
.highlight .mh {
|
||||
color: #099;
|
||||
}
|
||||
.highlight .mi {
|
||||
color: #099;
|
||||
}
|
||||
.highlight .mo {
|
||||
color: #099;
|
||||
}
|
||||
.highlight .sb {
|
||||
color: #d14;
|
||||
}
|
||||
.highlight .sc {
|
||||
color: #d14;
|
||||
}
|
||||
.highlight .sd {
|
||||
color: #d14;
|
||||
}
|
||||
.highlight .s2 {
|
||||
color: #d14;
|
||||
}
|
||||
.highlight .se {
|
||||
color: #d14;
|
||||
}
|
||||
.highlight .sh {
|
||||
color: #d14;
|
||||
}
|
||||
.highlight .si {
|
||||
color: #d14;
|
||||
}
|
||||
.highlight .sx {
|
||||
color: #d14;
|
||||
}
|
||||
.highlight .sr {
|
||||
color: #009926;
|
||||
}
|
||||
.highlight .s1 {
|
||||
color: #d14;
|
||||
}
|
||||
.highlight .ss {
|
||||
color: #990073;
|
||||
}
|
||||
.highlight .bp {
|
||||
color: #999;
|
||||
}
|
||||
.highlight .vc {
|
||||
color: #008080;
|
||||
}
|
||||
.highlight .vg {
|
||||
color: #008080;
|
||||
}
|
||||
.highlight .vi {
|
||||
color: #008080;
|
||||
}
|
||||
.highlight .il {
|
||||
color: #099;
|
||||
}
|
||||
|
||||
/*# sourceMappingURL=main.css.map */
|
||||
@@ -10,10 +10,6 @@ import com.github.gtache.autosubtitle.subtitle.OutputFormat;
|
||||
import com.github.gtache.autosubtitle.subtitle.extractor.ExtractionModel;
|
||||
import com.github.gtache.autosubtitle.subtitle.extractor.ExtractionModelProvider;
|
||||
import com.github.gtache.autosubtitle.subtitle.impl.FontImpl;
|
||||
|
||||
import javax.inject.Inject;
|
||||
import javax.inject.Singleton;
|
||||
|
||||
import javafx.beans.binding.Bindings;
|
||||
import javafx.beans.property.IntegerProperty;
|
||||
import javafx.beans.property.ObjectProperty;
|
||||
@@ -27,6 +23,8 @@ import javafx.collections.FXCollections;
|
||||
import javafx.collections.ObservableList;
|
||||
import javafx.collections.ObservableMap;
|
||||
|
||||
import javax.inject.Inject;
|
||||
import javax.inject.Singleton;
|
||||
import java.util.Map;
|
||||
|
||||
/**
|
||||
@@ -55,7 +53,7 @@ public class FXParametersModel implements ParametersModel {
|
||||
this.extractionModelProvider = new SimpleObjectProperty<>(defaultProvider);
|
||||
this.availableExtractionModels = FXCollections.observableArrayList(defaultProvider.getAvailableExtractionModels());
|
||||
this.extractionModel = new SimpleObjectProperty<>(defaultProvider.getDefaultExtractionModel());
|
||||
this.availableOutputFormats = FXCollections.unmodifiableObservableList(FXCollections.observableArrayList(OutputFormat.SRT));
|
||||
this.availableOutputFormats = FXCollections.unmodifiableObservableList(FXCollections.observableArrayList(OutputFormat.values()));
|
||||
this.outputFormat = new SimpleObjectProperty<>(OutputFormat.SRT);
|
||||
this.availableFontFamilies = FXCollections.unmodifiableObservableList(FXCollections.observableArrayList("Arial"));
|
||||
this.fontName = new SimpleStringProperty(defaultFontFamily);
|
||||
|
||||
@@ -2,9 +2,7 @@
|
||||
|
||||
<?import javafx.geometry.Insets?>
|
||||
<?import javafx.scene.control.Label?>
|
||||
<?import javafx.scene.layout.ColumnConstraints?>
|
||||
<?import javafx.scene.layout.GridPane?>
|
||||
<?import javafx.scene.layout.RowConstraints?>
|
||||
<?import javafx.scene.layout.*?>
|
||||
<GridPane fx:id="setupGrid" hgap="10.0" vgap="10.0" xmlns="http://javafx.com/javafx/22"
|
||||
xmlns:fx="http://javafx.com/fxml/1"
|
||||
fx:controller="com.github.gtache.autosubtitle.gui.setup.fx.FXSetupController">
|
||||
@@ -12,8 +10,9 @@
|
||||
<ColumnConstraints hgrow="SOMETIMES"/>
|
||||
<ColumnConstraints hgrow="SOMETIMES"/>
|
||||
<ColumnConstraints hgrow="SOMETIMES"/>
|
||||
<ColumnConstraints hgrow="ALWAYS"/>
|
||||
<ColumnConstraints hgrow="SOMETIMES"/>
|
||||
<ColumnConstraints hgrow="SOMETIMES"/>
|
||||
<ColumnConstraints hgrow="ALWAYS"/>
|
||||
</columnConstraints>
|
||||
<rowConstraints>
|
||||
<RowConstraints vgrow="SOMETIMES"/>
|
||||
|
||||
Reference in New Issue
Block a user