use of org.saxing.a0041_wemedia.domain.entity.VideoDO in project java-example by saxingz.
the class VideoLogicImpl method downloadVideo.
@Override
public Boolean downloadVideo(Long id) throws IOException {
synchronized (DOWNLOAD_LOCK) {
log.info("downloadVideo: id: " + id);
try {
Thread.sleep(500 + new Random().nextInt(1000));
} catch (InterruptedException ignored) {
}
VideoDO videoDO = this.getById(id);
if (Objects.isNull(videoDO)) {
return false;
}
// 判断是否已下载完成
if (Objects.equals(videoDO.getDownloadStatus(), DownLoadStatus.DOWNLOADED.getCode())) {
return true;
}
String videoId = videoDO.getVideoId();
String videoPathStr = BASE_PATH + id;
Path videoPath = Paths.get(videoPathStr);
boolean isFirstNull = false;
if (!Files.exists(videoPath)) {
isFirstNull = true;
Files.createDirectories(videoPath);
}
List<Path> fileList = Files.list(videoPath).collect(Collectors.toList());
// 英文字幕
Path enVtt = fileList.stream().filter(p -> p.getFileName().toString().endsWith("en.vtt")).findFirst().orElse(null);
// 中文字幕
Path zhHansvtt = fileList.stream().filter(p -> p.getFileName().toString().endsWith(".zh-Hans.vtt")).findFirst().orElse(null);
// 原始视频文件
Path originVideoFile = fileList.stream().filter(p -> p.getFileName().toString().endsWith(".mp4")).findFirst().orElse(null);
// 原始音频文件
Path originAudioFile = fileList.stream().filter(p -> p.getFileName().toString().endsWith(".webm") || p.getFileName().toString().endsWith(".m4a")).findFirst().orElse(null);
// 校验下载项
if ((Objects.isNull(enVtt) || Objects.isNull(zhHansvtt) || Objects.isNull(originVideoFile) || Objects.isNull(originAudioFile)) && !isFirstNull) {
// 如果不支持断点续传了,再把这个注释解开
if (Files.list(videoPath).count() > 0) {
new File(videoPathStr).renameTo(new File(videoPathStr + "-" + UUID.fastUUID().toString()));
if (!Files.exists(videoPath)) {
Files.createDirectories(videoPath);
}
}
}
// 下载
if (Objects.isNull(enVtt) || Objects.isNull(zhHansvtt) || Objects.isNull(originVideoFile) || Objects.isNull(originAudioFile)) {
String outputFile = videoPathStr + "\\" + id + ".%(ext)s";
// 重新下载
List<String> arguments = new ArrayList<>(Arrays.asList(YOUTUBE_DL_PATH, "--write-sub", "--write-auto-sub", "--sub-lang", "en,zh-Hans", "--sub-format", "vtt", "-f", "\"bestvideo[ext=mp4]+bestaudio[ext=m4a]/best[ext=mp4]/best\"", "--no-check-certificate", "-o", "\"" + outputFile + "\"", "--proxy", "socks5://127.0.0.1:51837/", "https://www.youtube.com/watch?v=" + videoId));
try {
log.info("arguments: " + String.join(" ", arguments));
ProcessRunner.run(arguments);
String videoTitle = videoDO.getVideoTitle();
String titleFile = videoPathStr + "\\" + id + "-title.txt";
Path titleFilePath = Paths.get(titleFile);
if (!Files.exists(titleFilePath)) {
Files.write(titleFilePath, videoTitle.getBytes(), StandardOpenOption.WRITE, StandardOpenOption.CREATE);
}
} catch (ProcessException | InterruptedException e) {
e.printStackTrace();
log.error(e.toString());
}
}
// 刷新列表
fileList = Files.list(videoPath).collect(Collectors.toList());
// 英文字幕
enVtt = fileList.stream().filter(p -> p.getFileName().toString().endsWith("en.vtt")).findFirst().orElse(null);
// 中文字幕
zhHansvtt = fileList.stream().filter(p -> p.getFileName().toString().endsWith(".zh-Hans.vtt")).findFirst().orElse(null);
// 原始视频文件
originVideoFile = fileList.stream().filter(p -> p.getFileName().toString().endsWith(".mp4")).findFirst().orElse(null);
// 原始音频文件
originAudioFile = fileList.stream().filter(p -> p.getFileName().toString().endsWith(".webm") || p.getFileName().toString().endsWith(".m4a")).findFirst().orElse(null);
// 校验下载项
if (Objects.isNull(enVtt) || Objects.isNull(zhHansvtt) || Objects.isNull(originVideoFile) || Objects.isNull(originAudioFile)) {
// 下载失败,返回
log.error("下载失败,返回 videoId: " + id);
return false;
} else {
log.info("下载成功 videoId: " + id);
videoDO.setDownloadStatus(DownLoadStatus.DOWNLOADED.getCode());
this.saveOrUpdate(videoDO);
return true;
}
}
}
use of org.saxing.a0041_wemedia.domain.entity.VideoDO in project java-example by saxingz.
the class VideoLogicImpl method rebuild.
@Override
public Boolean rebuild(Long id) throws IOException {
synchronized (REBUILD_VIDEO_LOCK) {
log.info("rebuild: id: " + id);
VideoDO videoDO = this.getById(id);
if (Objects.isNull(videoDO)) {
log.error("视频不存在, video表id: " + id);
return false;
}
if (!Objects.equals(videoDO.getDownloadStatus(), DownLoadStatus.DOWNLOADED.getCode())) {
log.info("视频未下载,开始下载 videoId: " + id);
downloadVideo(id);
}
videoDO = this.getById(id);
if (!Objects.equals(videoDO.getDownloadStatus(), DownLoadStatus.DOWNLOADED.getCode())) {
log.info("视频不存在 videoId: " + id);
return false;
}
if (Objects.equals(videoDO.getRebuildStatus(), RebuildStatus.REBUILDED.getCode())) {
return true;
}
String videoPathStr = BASE_PATH + id;
Path videoPath = Paths.get(videoPathStr);
if (!Files.exists(videoPath)) {
Files.createDirectories(videoPath);
}
List<Path> fileList = Files.list(videoPath).collect(Collectors.toList());
// 英文字幕
Path enVtt = fileList.stream().filter(p -> p.getFileName().toString().endsWith("en.vtt")).findFirst().orElse(null);
// 中文字幕
Path zhHansvtt = fileList.stream().filter(p -> p.getFileName().toString().endsWith(".zh-Hans.vtt")).findFirst().orElse(null);
// 原始视频文件
Path originVideoFile = fileList.stream().filter(p -> p.getFileName().toString().endsWith(".mp4")).findFirst().orElse(null);
// 原始音频文件
Path originAudioFile = fileList.stream().filter(p -> p.getFileName().toString().endsWith(".webm") || p.getFileName().toString().endsWith(".m4a")).findFirst().orElse(null);
if (Objects.isNull(originAudioFile)) {
log.error("没有音频文件 videoId: " + id);
return false;
}
// 1. convert to mp3
log.info("1. convert to mp3, videoId: " + id);
convertToMp3(originAudioFile);
// 2. subtitle vtt -> srt
log.info("2. subtitle vtt -> srt, videoId: " + id);
convertToSrt(zhHansvtt, "zh");
convertToSrt(enVtt, "en");
// 3. merge subtitle
log.info("3. merge subtitle, videoId: " + id);
fileList = Files.list(videoPath).collect(Collectors.toList());
Path enSrt = fileList.stream().filter(p -> p.getFileName().toString().endsWith("en.srt")).findFirst().orElse(null);
Path zhSrt = fileList.stream().filter(p -> p.getFileName().toString().endsWith("zh.srt")).findFirst().orElse(null);
if (Objects.isNull(enSrt) || Objects.isNull(zhSrt)) {
log.error("字幕不全, videoId: " + id);
return false;
}
try {
mergeSubtitle(enSrt, zhSrt);
} catch (InterruptedException e) {
e.printStackTrace();
log.error("字幕合并失败, videoId: " + id);
}
// 4. merge subtitle watermark video
log.info("4. merge subtitle watermark video, videoId: " + id);
fileList = Files.list(videoPath).collect(Collectors.toList());
Path mixedSrt = fileList.stream().filter(p -> p.getFileName().toString().endsWith("mixed.srt")).findFirst().orElse(null);
mergeSubtitleAndVideo(originVideoFile, mixedSrt);
// 5. merge video audio
log.info("5. merge video audio, videoId: " + id);
fileList = Files.list(videoPath).collect(Collectors.toList());
Path subtitleVideo = fileList.stream().filter(p -> p.getFileName().toString().endsWith("subtitle.mp4")).findFirst().orElse(null);
Path mp3Audio = fileList.stream().filter(p -> p.getFileName().toString().endsWith(".mp3")).findFirst().orElse(null);
if (Objects.isNull(subtitleVideo) || Objects.isNull(mp3Audio)) {
log.error("subtitleVideo 或 mp3Audio 不存在, videoId: " + id);
return false;
}
mergeVideoAndAudio(subtitleVideo, mp3Audio);
// 6. merge head and tail
log.info("6. merge head and tail, videoId: " + id);
fileList = Files.list(videoPath).collect(Collectors.toList());
Path audioVideoMp4 = fileList.stream().filter(p -> p.getFileName().toString().endsWith("audio.mp4")).findFirst().orElse(null);
if (Objects.isNull(audioVideoMp4)) {
log.error("audioVideo生成失败, videoId: " + id);
return false;
}
mergeHeadTail(audioVideoMp4, Paths.get(VIDEO_HEAD_PATH), Paths.get(VIDEO_TAIL_PATH));
// 9. 校验生成视频
log.info("7. 校验生成视频, videoId: " + id);
fileList = Files.list(videoPath).collect(Collectors.toList());
Path finalVideo = fileList.stream().filter(p -> p.getFileName().toString().endsWith("final.mp4")).findFirst().orElse(null);
if (Objects.isNull(finalVideo)) {
log.error("视频最后生成失败, videoId: " + id);
return false;
}
// 标记生成成功
videoDO.setRebuildStatus(RebuildStatus.REBUILDED.getCode());
this.updateById(videoDO);
log.info("视频生成成功!!!, videoId: " + id);
return true;
}
}
use of org.saxing.a0041_wemedia.domain.entity.VideoDO in project java-example by saxingz.
the class VideoController method listVideos.
/**
* 查看原始视频
*/
@ApiOperation("查看原始视频")
@ApiImplicitParams({ @ApiImplicitParam(name = "page", value = "页码", defaultValue = "1"), @ApiImplicitParam(name = "pageNum", value = "每页条数", defaultValue = "1") })
@PostMapping("/list")
public Page<VideoVO> listVideos(@RequestBody VideoDO video, @RequestParam @Min(value = 1, message = "页码不得少于1") Integer page, @RequestParam @Min(value = 1, message = "每页条数不得少于1") @Max(value = 100, message = "每页条数不大于100") Integer pageNum) {
LambdaQueryWrapper<VideoDO> queryWrapper = Wrappers.lambdaQuery();
queryWrapper.setEntity(video);
queryWrapper.like(StringUtils.isNotBlank(video.getChannelId()), VideoDO::getChannelId, video.getChannelId());
queryWrapper.like(StringUtils.isNotBlank(video.getChannelTitle()), VideoDO::getChannelTitle, video.getChannelTitle());
queryWrapper.like(StringUtils.isNotBlank(video.getVideoId()), VideoDO::getVideoId, video.getVideoId());
queryWrapper.like(StringUtils.isNotBlank(video.getVideoTitle()), VideoDO::getVideoTitle, video.getVideoTitle());
queryWrapper.like(StringUtils.isNotBlank(video.getDescription()), VideoDO::getDescription, video.getDescription());
queryWrapper.like(StringUtils.isNotBlank(video.getDownloadedUrl()), VideoDO::getDownloadedUrl, video.getDownloadedUrl());
video.setChannelId(null).setChannelTitle(null).setVideoId(null).setVideoTitle(null).setDescription(null).setDownloadedUrl(null);
Page<VideoDO> videoDOPage = videoLogic.page(new Page<>(page, pageNum), queryWrapper).addOrder(OrderItem.desc(TableInfoHelper.getTableInfo(VideoDO.class).getKeyProperty()));
Page<VideoVO> result = beanMapper.map(videoDOPage, new TypeBuilder<Page<VideoDO>>() {
}.build(), new TypeBuilder<Page<VideoVO>>() {
}.build());
if (result.getSize() > 0) {
result.getRecords().forEach(r -> r.setTransferList(transferLogic.list(new QueryWrapper<>(new TransferDO().setVideoId(r.getId())))));
}
return result;
}
use of org.saxing.a0041_wemedia.domain.entity.VideoDO in project java-example by saxingz.
the class ChannelLogic method scanChannel.
@Override
public void scanChannel(DateTime startDate, DateTime endDate, String channelId) {
ChannelDO channelDO = this.lambdaQuery().ge(ChannelDO::getChannelId, channelId).one();
if (Objects.isNull(channelDO)) {
log.error("没有本频道: channelId: " + channelId);
return;
}
List<SearchResult> searchResults = scanResult(startDate, endDate, channelId);
if (CollectionUtils.isEmpty(searchResults)) {
return;
}
searchResults.forEach(searchResult -> {
String kind = searchResult.getId().getKind();
if (!Objects.equals(kind, "youtube#video")) {
return;
}
log.info("找到一个youtube视频 " + searchResult);
String videoId = searchResult.getId().getVideoId();
VideoDO video = videoLogic.lambdaQuery().eq(VideoDO::getVideoId, videoId).one();
if (Objects.nonNull(video)) {
return;
}
String channelTitle = searchResult.getSnippet().getChannelTitle();
String videoTitle = searchResult.getSnippet().getTitle();
String description = searchResult.getSnippet().getDescription();
com.google.api.client.util.DateTime publishedAt = searchResult.getSnippet().getPublishedAt();
String thumbnails = searchResult.getSnippet().getThumbnails().getHigh().getUrl();
video = new VideoDO().setPlatform(Platform.YOUTUBE.getName()).setChannelId(channelId).setChannelTitle(channelTitle).setVideoId(videoId).setVideoTitle(videoTitle).setDescription(description).setPublishTime(new Date(publishedAt.getValue())).setThumbnails(thumbnails);
videoLogic.saveOrUpdate(video);
});
// 更新channel最后follow时间
com.google.api.client.util.DateTime lastPublishedAt = searchResults.get(searchResults.size() - 1).getSnippet().getPublishedAt();
channelDO.setFollowTime(new Date(lastPublishedAt.getValue()));
this.updateById(channelDO);
}
Aggregations