没想到这么多人需要这些功能,本人整合了在这个最新的工具中,打开有教程
本人的最新工具:wondertool: 硬字幕提取、文字物体识别、图片缩放工具 (gitee.com)
3.0版本下载地址:wondertool 发行版 - Gitee.com
下载这4个包解压即可:
WonderTool_win-x64.zip
WonderTool_win-x64.z01
WonderTool_win-x64.z03
WonderTool_win-x64.z02
原文如下:
最近博主闲下来了,思考人生接下来的方向,无聊时帮别人做了点小东西,贡献出来:
jre-17.0.7_win-x64的生成方式:
以管理员方式运行PowerShell执行命令:
cd $env:JAVA_HOME
jlink --no-header-files --no-man-pages --compress=2 --strip-debug --add-modules java.base,java.xml,java.desktop,jdk.management.agent --output E:\jre-17.0.7_win-x64
内部参数:
java -Dfile.encoding=UTF-8 -jar single-subtitle-text-1.0.0.jar
使用教程:
注意该图片的两个文件夹,都在下面这个软件的安装目录中。
VideoSubFinderWXW 拿来做字幕图片截取捕获,这是下载地址:
VideoSubFinder download | SourceForge.net
下载安装完成后,步骤:打开视频框选字幕位置,清空所有图片(之前识别的图片),开始识别。
捕获完在安装目录图片所示的第一个文件夹RGBImages中,PearOCR可以安装成浏览器应用可以离线识别,pearOCR官网如下:
PearOCR,在线图片转文字,免费OCR,在线图片文字提取,本地运算,无上传
上传RGBImages所有图片识别完后导出为txt。(如果后续出现问题,文件路径及文件名不建议带有中文)
接下来是我开发的小工具(代码已开源到github上),下载地址如下,
Release single-subtitle-text · Aaron-CJ/single-subtitle-text · GitHub
下载single-subtitle-text_win-x64.zip解压,看到single-subtitle-text_win-x64.exe。
安全无毒,下面是代码:
package pers.lcj.tool;
import lombok.extern.log4j.Log4j2;
import java.io.BufferedReader;
import java.io.BufferedWriter;
import java.io.FileReader;
import java.io.IOException;
import java.nio.charset.StandardCharsets;
import java.nio.file.Files;
import java.nio.file.Path;
import java.nio.file.Paths;
import java.util.HashMap;
import java.util.Map;
import java.util.Scanner;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
/**
* Created by Aaron on 2023/4/28 0:29
*/
@Log4j2
public class Main {
public static void main(String[] args) {
Scanner scanner = new Scanner(System.in, "GBK");
System.out.println("请输入导入文件路径:");
Path inputPath = getPath(scanner, "导入文件");
System.out.println("请输入导出目录路径:");
Path outputPath = getPath(scanner, "导出目录");
Map<String, String> result = readFile(inputPath.toString());
writeOutputFiles(outputPath, result);
}
public static Path getPath(Scanner sc, String pathType) {
Path path;
do {
String inputPath = sc.nextLine().replaceAll("^\"+|\"+$", "");
path = Paths.get(inputPath);
if (pathType.equals("导入文件") && !Files.isRegularFile(path)) {
System.out.println("输入路径不是一个有效文件路径,请重新输入:");
path = null;
} else if (pathType.equals("导出目录") && !Files.isDirectory(path)) {
System.out.println("输入路径不是一个有效文件路径,请重新输入:");
path = null;
}
} while (path == null);
return path;
}
private static final int BUFFER_SIZE = 8192;
private static final Pattern REGEX_PATTERN = Pattern.compile("(?<=-\\s)([^.]+)(?=\\.jpeg)");
private static Map<String, String> readFile(String inputFilePath) {
Map<String, String> result = new HashMap<>();
try (BufferedReader br = new BufferedReader(new FileReader(inputFilePath), BUFFER_SIZE)) {
StringBuilder currentValueBuilder = new StringBuilder(1024); // 初始化StringBuilder大小,避免过多扩容
Matcher matcher;
String key = null;
String currentLine;
while ((currentLine = br.readLine()) != null) {
matcher = REGEX_PATTERN.matcher(currentLine);
if (matcher.find()) {
if (key != null) {
String value = currentValueBuilder.toString().trim();
result.put(key, value.isEmpty() ? "null" : value); // 添加新的结果到Map中,并清空StringBuilder
currentValueBuilder.setLength(0);
}
key = matcher.group(1);
} else if (key != null) { // 对currentValue进行构建
currentValueBuilder.append(currentLine.trim()).append(" "); // 添加空格,避免拼接相邻字符串时出现语义混淆
}
}
if (key != null) { // 处理最后一个结果
result.put(key, currentValueBuilder.toString().trim().replace(" ------------ prower by PearOCR.com ------------", ""));
}
} catch (IOException e) {
log.error("Error reading file:", e);
}
return result;
}
private static void writeOutputFiles(Path outputFolderPath, Map<String, String> result) {
System.out.println("正在处理,请稍等......");
result.entrySet().parallelStream().forEach(entry -> {
String fileName = entry.getKey();
Path txtFilePath = outputFolderPath.resolve(fileName + ".txt");
try (BufferedWriter bw = Files.newBufferedWriter(txtFilePath, StandardCharsets.UTF_8)) {
bw.write(entry.getValue());
} catch (IOException e) {
log.error("Error write file:", e);
}
});
System.out.println("文件总计(个):" + result.size());
}
}
Gradle 8.1.1引入的依赖:
plugins {
// Java插件,该插件提供了Java应用和库的基本功能
id 'java'
// lombok插件,该插件支持在Java项目中使用Lombok注解
id 'io.freefair.lombok' version '8.0.1'
}
group = 'pers.lcj.tool'
version = '1.0.0'
repositories {
mavenLocal {
url 'file:///D:/m2/repository'
}
maven { url 'https://maven.aliyun.com/repository/public/' }
mavenCentral()
}
dependencies {
// Lombok
compileOnly 'org.projectlombok:lombok:1.18.26'
annotationProcessor 'org.projectlombok:lombok:1.18.26'
// Log4j2
implementation 'org.apache.logging.log4j:log4j-api:2.20.0'
implementation 'org.apache.logging.log4j:log4j-core:2.20.0'
implementation 'org.apache.logging.log4j:log4j-slf4j-impl:2.20.0'
// JUnit 5
testImplementation 'org.junit.jupiter:junit-jupiter:5.9.3'
}
jar {
duplicatesStrategy = 'exclude'
from {
configurations.compileClasspath.collect { it.isDirectory() ? it : zipTree(it) }
}
manifest {
attributes 'Main-Class': 'pers.lcj.tool.Main'
}
}
test {
useJUnitPlatform()
}
log4j2.properties log4j2 配置文件
# 设置日志级别为info
rootLogger.level = info
# 控制台Appender的配置
appender.console.type = Console
appender.console.name = consoleLogger
appender.console.layout.type = PatternLayout
appender.console.layout.pattern = %d{yyyy-MM-dd HH:mm:ss} %-5p %c{1}:%L - %m%n
# 根日志记录器引用控制台Appender
rootLogger.appenderRef.stdout.ref = consoleLogger
# 日志文件存放路径
property.basePath = logs
# 组件Appender的名称、模式、路径和滚动策略
appender.rolling.type = RollingFile
appender.rolling.name = fileLogger
appender.rolling.fileName= ${basePath}/sst.log
appender.rolling.filePattern= ${basePath}/sst_%d{yyyyMMdd}.log.gz
appender.rolling.layout.type = PatternLayout
appender.rolling.layout.pattern = %d{yyyy-MM-dd HH:mm:ss.SSS} %level [%t] [%l] - %msg%n
appender.rolling.policies.type = Policies
# 组件Appender的滚动策略,包括按大小滚动和按时间滚动两种策略。
appender.rolling.policies.size.type = SizeBasedTriggeringPolicy
# 按大小滚动策略大小限制
appender.rolling.policies.size.size = 310MB
appender.rolling.policies.time.type = TimeBasedTriggeringPolicy
# 按时间滚动策略间隔时间(单位:天)
appender.rolling.policies.time.interval = 1
# 按时间滚动策略是否调整时区
appender.rolling.policies.time.modulate = true
# 组件Appender的滚动策略,包括按大小滚动和按时间滚动两种策略。
appender.rolling.strategy.type = DefaultRolloverStrategy
# 组件Appender的删除策略。
appender.rolling.strategy.delete.type = Delete
# 删除文件所在目录路径。
appender.rolling.strategy.delete.basePath = ${basePath}
# 删除最旧的文件之前可以在目录中保留的最大文件数。默认值为0,这意味着不会删除任何文件。
appender.rolling.strategy.delete.maxDepth = 92
# 用于指定删除文件的条件类型,按最后修改时间删除。
appender.rolling.strategy.delete.ifLastModified.type = IfLastModified
# 删除所有早于92天的文件。
appender.rolling.strategy.delete.ifLastModified.age = 92d
# 配置根日志记录器,引用组件Appender。
rootLogger.appenderRef.rolling.ref = fileLogger
打开single-subtitle-text_win-x64.exe,根据提示输入该txt文本文件路径和输入安装目录图片所示的第二个文件夹TXTResults的路径,生成相应的TXTResults后
点击软件ocr菜单中的这个即可生成你想要的视频字幕了,贡献给所有做视频的朋友,市面上做这个的基本都收费,特别视频多且视频时长 长的工作,可以带来助力,大大缩短工作时长,但毕竟ocr识别不是完全准确的,还是需要一些人工审核。虽然意义不是很大但是对同声传译的视频提取字幕,新闻传播类等的二次制作等有帮助,以及博主不知道的领域等有帮助。