deploy 04191544
This commit is contained in:
parent
01e04064cb
commit
6b2a60de32
@ -62,8 +62,19 @@ public class ReportController {
|
|||||||
return "photo";
|
return "photo";
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 报告 JSON 中与「服务回顾短片」相关的字段(与小程序 / H5 共用契约)。
|
||||||
|
* <ul>
|
||||||
|
* <li>{@code highlightVideoUrl} — 成片 MP4;库内为相对路径 {@code /api/upload/image/...} 或历史绝对 URL;接口统一为可访问绝对 URL。</li>
|
||||||
|
* <li>{@code highlightShareCoverUrl} — 成片首帧 JPEG,用于分享卡片封面;截帧失败时为 {@code null},前端按 utils 中分享封面降级链处理。</li>
|
||||||
|
* <li>{@code highlightPosterUrl} — 预留(画布海报等);当前恒为 {@code null},前端可用 {@code highlightShareCoverUrl}。</li>
|
||||||
|
* <li>{@code highlightVideoStatus} — {@code processing} | {@code done} | {@code failed} 等。</li>
|
||||||
|
* </ul>
|
||||||
|
*/
|
||||||
private void putHighlightFields(Map<String, Object> target, Report r) {
|
private void putHighlightFields(Map<String, Object> target, Report r) {
|
||||||
target.put("highlightVideoUrl", r.getHighlightVideoUrl() != null ? fullUrl(r.getHighlightVideoUrl()) : null);
|
target.put("highlightVideoUrl", r.getHighlightVideoUrl() != null ? fullUrl(r.getHighlightVideoUrl()) : null);
|
||||||
|
target.put("highlightShareCoverUrl", r.getHighlightShareCoverUrl() != null ? fullUrl(r.getHighlightShareCoverUrl()) : null);
|
||||||
|
target.put("highlightPosterUrl", null);
|
||||||
target.put("highlightVideoStatus", r.getHighlightVideoStatus());
|
target.put("highlightVideoStatus", r.getHighlightVideoStatus());
|
||||||
target.put("highlightVideoError", r.getHighlightVideoError());
|
target.put("highlightVideoError", r.getHighlightVideoError());
|
||||||
target.put("highlightDurationSec", r.getHighlightDurationSec());
|
target.put("highlightDurationSec", r.getHighlightDurationSec());
|
||||||
|
|||||||
@ -75,4 +75,11 @@ public class Report {
|
|||||||
/** 失败原因归类:material | service | network | unknown(对宠主展示,无技术细节) */
|
/** 失败原因归类:material | service | network | unknown(对宠主展示,无技术细节) */
|
||||||
@Column(name = "highlight_fail_reason", length = 16)
|
@Column(name = "highlight_fail_reason", length = 16)
|
||||||
private String highlightFailReason;
|
private String highlightFailReason;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 成片首帧截图(竖屏内一帧),用于分享卡片封面等;相对路径如 {@code /api/upload/image/年/月/日/xxx_cover.jpg}。
|
||||||
|
* 与成片 MP4 同目录;仅当 highlight 状态为 done 且截帧成功时有值。
|
||||||
|
*/
|
||||||
|
@Column(name = "highlight_share_cover_url", length = 500)
|
||||||
|
private String highlightShareCoverUrl;
|
||||||
}
|
}
|
||||||
|
|||||||
@ -143,6 +143,7 @@ public class ReportHighlightVideoService {
|
|||||||
report.setHighlightVideoStatus("processing");
|
report.setHighlightVideoStatus("processing");
|
||||||
report.setHighlightVideoError(null);
|
report.setHighlightVideoError(null);
|
||||||
report.setHighlightFailReason(null);
|
report.setHighlightFailReason(null);
|
||||||
|
report.setHighlightShareCoverUrl(null);
|
||||||
report.setHighlightComposeMode(mode);
|
report.setHighlightComposeMode(mode);
|
||||||
report.setUpdateTime(LocalDateTime.now());
|
report.setUpdateTime(LocalDateTime.now());
|
||||||
reportMapper.save(report);
|
reportMapper.save(report);
|
||||||
@ -356,13 +357,20 @@ public class ReportHighlightVideoService {
|
|||||||
Path finalPath = outDir.resolve(filename);
|
Path finalPath = outDir.resolve(filename);
|
||||||
Files.copy(afterBgm, finalPath, StandardCopyOption.REPLACE_EXISTING);
|
Files.copy(afterBgm, finalPath, StandardCopyOption.REPLACE_EXISTING);
|
||||||
|
|
||||||
String publicBase = baseUrl.endsWith("/") ? baseUrl.substring(0, baseUrl.length() - 1) : baseUrl;
|
String videoRel = "/api/upload/image/" + datePath + "/" + filename;
|
||||||
String url = publicBase + "/api/upload/image/" + datePath + "/" + filename;
|
String coverFilename = filename.endsWith(".mp4")
|
||||||
|
? filename.substring(0, filename.length() - 4) + "_cover.jpg"
|
||||||
|
: filename + "_cover.jpg";
|
||||||
|
Path coverPath = outDir.resolve(coverFilename);
|
||||||
|
String coverRel = extractVideoCoverFrame(finalPath, coverPath)
|
||||||
|
? "/api/upload/image/" + datePath + "/" + coverFilename
|
||||||
|
: null;
|
||||||
|
|
||||||
int durationRoundedSec = (int) Math.ceil(totalDurationSec);
|
int durationRoundedSec = (int) Math.ceil(totalDurationSec);
|
||||||
synchronized (lockFor(reportId)) {
|
synchronized (lockFor(reportId)) {
|
||||||
reportMapper.findByIdAndDeletedFalse(reportId).ifPresent(r -> {
|
reportMapper.findByIdAndDeletedFalse(reportId).ifPresent(r -> {
|
||||||
r.setHighlightVideoUrl(url);
|
r.setHighlightVideoUrl(videoRel);
|
||||||
|
r.setHighlightShareCoverUrl(coverRel);
|
||||||
r.setHighlightVideoStatus("done");
|
r.setHighlightVideoStatus("done");
|
||||||
r.setHighlightVideoError(null);
|
r.setHighlightVideoError(null);
|
||||||
r.setHighlightFailReason(null);
|
r.setHighlightFailReason(null);
|
||||||
@ -451,6 +459,26 @@ public class ReportHighlightVideoService {
|
|||||||
/**
|
/**
|
||||||
* 服务前第一张 | 服务后第一张 左右拼接为 1080×1920 竖屏对比图(左前右后)。
|
* 服务前第一张 | 服务后第一张 左右拼接为 1080×1920 竖屏对比图(左前右后)。
|
||||||
*/
|
*/
|
||||||
|
/**
|
||||||
|
* 从成片 MP4 截取首帧为 JPEG,供分享卡片等使用。
|
||||||
|
*
|
||||||
|
* @return 是否写出有效文件
|
||||||
|
*/
|
||||||
|
private boolean extractVideoCoverFrame(Path mp4, Path outJpg) {
|
||||||
|
try {
|
||||||
|
int code = runFfmpeg(List.of(
|
||||||
|
ffmpegBinary, "-y",
|
||||||
|
"-i", mp4.toString(),
|
||||||
|
"-map", "0:v:0",
|
||||||
|
"-frames:v", "1",
|
||||||
|
"-q:v", "2",
|
||||||
|
outJpg.toString()));
|
||||||
|
return code == 0 && Files.isRegularFile(outJpg);
|
||||||
|
} catch (Exception e) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
private boolean buildComparisonCover(Path beforeFile, Path afterFile, Path outJpg) throws Exception {
|
private boolean buildComparisonCover(Path beforeFile, Path afterFile, Path outJpg) throws Exception {
|
||||||
String fc = "[0:v]scale=540:1920:force_original_aspect_ratio=decrease,pad=540:1920:(ow-iw)/2:(oh-ih)/2,setsar=1[va];"
|
String fc = "[0:v]scale=540:1920:force_original_aspect_ratio=decrease,pad=540:1920:(ow-iw)/2:(oh-ih)/2,setsar=1[va];"
|
||||||
+ "[1:v]scale=540:1920:force_original_aspect_ratio=decrease,pad=540:1920:(ow-iw)/2:(oh-ih)/2,setsar=1[vb];"
|
+ "[1:v]scale=540:1920:force_original_aspect_ratio=decrease,pad=540:1920:(ow-iw)/2:(oh-ih)/2,setsar=1[vb];"
|
||||||
|
|||||||
Loading…
Reference in New Issue
Block a user