Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat: 视频播放添加Vtt缩略图 #107

Merged
merged 2 commits into from
Jun 20, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
@@ -1,9 +1,12 @@
package com.jmal.clouddisk.controller.rest;

import cn.hutool.core.io.FileUtil;
import com.jmal.clouddisk.config.FileProperties;
import com.jmal.clouddisk.service.IShareService;
import com.jmal.clouddisk.util.FileContentTypeUtils;
import io.swagger.v3.oas.annotations.tags.Tag;
import lombok.RequiredArgsConstructor;
import org.jetbrains.annotations.NotNull;
import org.springframework.core.io.UrlResource;
import org.springframework.http.HttpHeaders;
import org.springframework.http.ResponseEntity;
Expand All @@ -12,6 +15,7 @@
import org.springframework.web.bind.annotation.RestController;

import java.io.IOException;
import java.net.MalformedURLException;
import java.nio.file.Path;
import java.nio.file.Paths;

Expand All @@ -27,20 +31,31 @@ public class VideoController {

@GetMapping("/video/hls/{username}/{fileId}.m3u8")
public ResponseEntity<UrlResource> m3u8(@PathVariable String username, @PathVariable String fileId) throws IOException {
Path m3u8Path = Paths.get(fileProperties.getRootDir(), fileProperties.getChunkFileDir(), username, fileProperties.getVideoTranscodeCache(), fileId, fileId + ".m3u8");
UrlResource videoResource = new UrlResource(m3u8Path.toUri());
return getUrlResourceResponseEntity(username, fileId, fileId + ".m3u8");
}

private @NotNull ResponseEntity<UrlResource> getUrlResourceResponseEntity(String username, String fileId, String suffix) throws MalformedURLException {
Path txtPath = Paths.get(fileProperties.getRootDir(), fileProperties.getChunkFileDir(), username, fileProperties.getVideoTranscodeCache(), fileId, suffix);
UrlResource videoResource = new UrlResource(txtPath.toUri());
return ResponseEntity.ok()
.header(HttpHeaders.CONTENT_TYPE, "application/vnd.apple.mpegurl")
.header(HttpHeaders.CONTENT_TYPE, FileContentTypeUtils.getContentType(FileUtil.extName(suffix)))
.header(HttpHeaders.CACHE_CONTROL, "max-age=600")
.body(videoResource);
}

@GetMapping("/video/hls/{username}/{fileId}.vtt")
public ResponseEntity<UrlResource> vtt(@PathVariable String username, @PathVariable String fileId) throws IOException {
return getUrlResourceResponseEntity(username, fileId, fileId + ".vtt");
}

@GetMapping("/video/hls/{username}/{fileId}-vtt.jpg")
public ResponseEntity<UrlResource> vttPNG(@PathVariable String username, @PathVariable String fileId) throws IOException {
return getUrlResourceResponseEntity(username, fileId, fileId + "-vtt.jpg");
}

@GetMapping("/video/hls/{username}/{fileId}-{index}.ts")
public ResponseEntity<UrlResource> ts(@PathVariable String username, @PathVariable String fileId, @PathVariable String index) throws IOException {
Path m3u8Path = Paths.get(fileProperties.getRootDir(), fileProperties.getChunkFileDir(), username, fileProperties.getVideoTranscodeCache(), fileId, fileId + "-" + index + ".ts");
UrlResource videoResource = new UrlResource(m3u8Path.toUri());
return ResponseEntity.ok()
.header(HttpHeaders.CONTENT_TYPE, "application/vnd.apple.mpegurl")
.body(videoResource);
return getUrlResourceResponseEntity(username, fileId, fileId + "-" + index + ".ts");
}

@GetMapping("/public/video/hls/{shareId}/{shareToken}/{username}/{fileId}.m3u8")
Expand All @@ -49,6 +64,12 @@ public ResponseEntity<UrlResource> publicM3u8(@PathVariable String username, @Pa
return m3u8(username, fileId);
}

@GetMapping("/public/video/hls/{shareId}/{shareToken}/{username}/{fileId}.vtt")
public ResponseEntity<UrlResource> publicVtt(@PathVariable String username, @PathVariable String fileId, @PathVariable String shareId, @PathVariable String shareToken) throws IOException {
shareService.validShare(shareToken, shareId);
return vtt(username, fileId);
}

@GetMapping("/public/video/hls/{shareId}/{shareToken}/{username}/{fileId}-{index}.ts")
public ResponseEntity<UrlResource> publicTs(@PathVariable String username, @PathVariable String fileId, @PathVariable String index, @PathVariable String shareId, @PathVariable String shareToken) throws IOException {
shareService.validShare(shareToken, shareId);
Expand Down
13 changes: 6 additions & 7 deletions src/main/java/com/jmal/clouddisk/lucene/LuceneService.java
Original file line number Diff line number Diff line change
Expand Up @@ -370,17 +370,16 @@ private boolean checkFileContent(File file) {
return false;
}
String type = FileTypeUtil.getType(file);
if (MyFileUtils.hasContentFile(type)) return true;
String charset = UniversalDetector.detectCharset(file);
if (StrUtil.isNotBlank(charset)) {
if (fileProperties.getSimText().contains(type)) {
return true;
}
if (MyFileUtils.hasContentFile(type)) {
return true;
}
if (fileProperties.getSimText().contains(type)) {
return true;
}
return MyFileUtils.hasCharset(file);
} catch (Exception e) {
return false;
}
return false;
}


Expand Down
4 changes: 2 additions & 2 deletions src/main/java/com/jmal/clouddisk/ocr/OcrService.java
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@
import cn.hutool.core.util.StrUtil;
import com.jmal.clouddisk.config.FileProperties;
import com.jmal.clouddisk.service.Constants;
import com.jmal.clouddisk.video.FFMPEGCommand;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import net.sourceforge.tess4j.ITesseract;
Expand All @@ -18,7 +19,6 @@
import java.nio.file.Paths;

import static com.jmal.clouddisk.util.FFMPEGUtils.getWaitingForResults;
import static com.jmal.clouddisk.util.FFMPEGUtils.hasNoFFmpeg;


@Service
Expand Down Expand Up @@ -77,7 +77,7 @@ public String generateOrcTempImagePath(String username) {
* @return 预处理后的图片路径
*/
public String getPreprocessedOCRImage(String inputPath, String outputPath) {
if (hasNoFFmpeg()) {
if (FFMPEGCommand.hasNoFFmpeg()) {
return outputPath;
}
if (FileUtil.exist(outputPath)) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -536,18 +536,11 @@ private void processImage(File file, Update update) {

public static String getContentType(File file, String contentType) {
try {
if (file == null) {
return contentType;
}
if (file.isDirectory()) {
return contentType;
}
if (contentType.contains(Constants.CONTENT_TYPE_MARK_DOWN)) {
return contentType;
}
String charset = UniversalDetector.detectCharset(file);
if (StrUtil.isNotBlank(charset) && StandardCharsets.UTF_8.name().equals(charset)) {
contentType = contentType + ";charset=utf-8";
if (MyFileUtils.hasCharset(file)) {
String charset = UniversalDetector.detectCharset(file);
if (StrUtil.isNotBlank(charset) && StandardCharsets.UTF_8.name().equals(charset)) {
contentType = contentType + ";charset=utf-8";
}
}
} catch (Exception e) {
log.error(e.getMessage(), e);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -319,7 +319,6 @@ public ResponseResult<Object> searchFileAndOpenDir(UploadApiParamDTO upload, Str
if (ossPath != null) {
return webOssService.searchFileAndOpenOssFolder(path, upload);
}

FileDocument fileDocument = mongoTemplate.findById(id, FileDocument.class, COLLECTION_NAME);
if (fileDocument == null) {
return ResultUtil.error(ExceptionType.FILE_NOT_FIND);
Expand Down Expand Up @@ -501,10 +500,12 @@ public Optional<FileDocument> getById(String id, Boolean content) {
Path filepath = Paths.get(fileProperties.getRootDir(), username, currentDirectory, fileDocument.getName());
if (Files.exists(filepath)) {
File file = filepath.toFile();
Charset charset = MyFileUtils.getFileCharset(file);
fileDocument.setDecoder(charset.name());
if (BooleanUtil.isTrue(content)) {
fileDocument.setContentText(FileUtil.readString(file, charset));
if (MyFileUtils.hasCharset(file)) {
Charset charset = MyFileUtils.getFileCharset(file);
fileDocument.setDecoder(charset.name());
if (BooleanUtil.isTrue(content)) {
fileDocument.setContentText(FileUtil.readString(file, charset));
}
}
}
return Optional.of(fileDocument);
Expand Down Expand Up @@ -545,7 +546,9 @@ public FileDocument previewTextByPath(String filePath, String username) throws C
throw new CommonException(ExceptionType.FILE_NOT_FIND);
}
FileDocument fileDocument = new FileDocument();
fileDocument.setDecoder(MyFileUtils.getFileCharset(file).name());
if (MyFileUtils.hasCharset(file)) {
fileDocument.setDecoder(MyFileUtils.getFileCharset(file).name());
}
Path path1 = path.subpath(0, path.getNameCount() - 1);
int rootCount = Paths.get(fileProperties.getRootDir(), username).getNameCount();
int path1Count = path1.getNameCount();
Expand Down
20 changes: 0 additions & 20 deletions src/main/java/com/jmal/clouddisk/util/FFMPEGUtils.java
Original file line number Diff line number Diff line change
Expand Up @@ -74,24 +74,4 @@ public static String getWaitingForResults(String outputPath, ProcessBuilder proc
return null;
}

/**
* 检查是否没有ffmpeg
* @return true: 没有ffmpeg
*/
public static boolean hasNoFFmpeg() {
try {
Process process = Runtime.getRuntime().exec("ffmpeg -version");
BufferedReader reader = new BufferedReader(new InputStreamReader(process.getInputStream()));
String line;
while ((line = reader.readLine()) != null) {
if (line.contains("ffmpeg version")) {
return false;
}
}
return true;
} catch (IOException e) {
log.error(e.getMessage(), e);
}
return true;
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -333,6 +333,7 @@ public static String getContentType(String ext) {
CONTENT_TYPE.put("m2t" , "video/mpeg");
CONTENT_TYPE.put("m3u" , "audio/x-mpegurl");
CONTENT_TYPE.put("m3u8" , "audio/x-mpegurl");
CONTENT_TYPE.put("vtt" , "audio/x-mpegurl");
CONTENT_TYPE.put("m4" , "application/x-m4");
CONTENT_TYPE.put("m4a" , "audio/mp4");
CONTENT_TYPE.put("m4b" , "audio/x-m4b");
Expand Down
33 changes: 30 additions & 3 deletions src/main/java/com/jmal/clouddisk/util/MyFileUtils.java
Original file line number Diff line number Diff line change
@@ -1,7 +1,10 @@
package com.jmal.clouddisk.util;

import cn.hutool.core.io.CharsetDetector;
import cn.hutool.core.io.FileTypeUtil;
import cn.hutool.core.io.FileUtil;
import cn.hutool.core.util.StrUtil;
import com.jmal.clouddisk.service.Constants;
import lombok.extern.slf4j.Slf4j;
import org.mozilla.universalchardet.UniversalDetector;

Expand All @@ -19,12 +22,37 @@
@Slf4j
public class MyFileUtils {

public static List<String> hasContentTypes = Arrays.asList("pdf", "ppt", "pptx", "doc", "docx", "drawio", "mind");
public static List<String> hasContentTypes = Arrays.asList("pdf", "drawio", "mind", "doc", "docx", "xls", "xlsx", "xlsm", "ppt", "pptx", "csv", "tsv", "dotm", "xlt", "xltm", "dot", "dotx", "xlam", "xla", "pages");

private MyFileUtils(){

}

public static boolean hasCharset(File file) {
try {
if (file == null) {
return false;
}
String suffix = FileUtil.extName(file.getName());
String contentType = FileContentTypeUtils.getContentType(suffix);
if (file.isDirectory()) {
return false;
}
if (contentType.contains(Constants.VIDEO)) {
return false;
}
if (contentType.contains(Constants.CONTENT_TYPE_IMAGE)) {
return false;
}
if (contentType.contains(Constants.AUDIO)) {
return false;
}
return CharsetDetector.detect(file) != null;
} catch (Exception e) {
return false;
}
}

/***
* 获取文件的字符编码
* @param file 源文件
Expand Down Expand Up @@ -52,8 +80,7 @@ public static boolean checkNoCacheFile(File file) {
}
String type = FileTypeUtil.getType(file);
if (hasContentFile(type)) return true;
String charset = UniversalDetector.detectCharset(file);
return !StrUtil.isBlank(charset);
return hasCharset(file);
} catch (Exception e) {
return false;
}
Expand Down
Loading