package com.yutou.bilibili.Tools; import com.yutou.bilibili.BiliBili.Datas.DanmuData; import java.io.File; import java.io.FileWriter; import java.io.IOException; import java.text.DecimalFormat; import java.util.ArrayList; import java.util.Arrays; import java.util.Date; import java.util.List; import java.util.concurrent.TimeUnit; public class AssTools { private final StringBuilder builder; private final Date startTime; private int y = 0; private List filters = new ArrayList<>(); private String alpha="80"; /** * 弹幕转换ass * @param title 标题 * @param startTime 录像起始时间 */ public AssTools(String title, Date startTime) { builder = new StringBuilder(); this.startTime = startTime; initAssHeader(title); } /** * 弹幕过滤器 * @param filter 过滤词 */ public void addFilter(String... filter) { filters.addAll(Arrays.asList(filter)); } /** * 弹幕透明度 * @param alpha 0 完全不透明 255 完全透明 */ public void setAlpha(int alpha){ this.alpha=Integer.toHexString(alpha); } private void addBuilder(String txt) { builder.append(txt).append("\n"); } private void initAssHeader(String title) { addBuilder("[Script Info]"); addBuilder("Title: " + title); addBuilder("Original Script: 本字幕由@yutou生成"); addBuilder("ScriptType: v4.00+"); addBuilder("Collisions: Normal"); addBuilder("PlayResX: 1920"); addBuilder("PlayResY: 1080"); addBuilder("Timer: 10.0000"); addBuilder(""); addBuilder("[V4+ Styles]"); addBuilder("Format: Name, Fontname, Fontsize, PrimaryColour, SecondaryColour, OutlineColour, BackColour, Bold, Italic, Underline, StrikeOut, ScaleX, ScaleY, Spacing, Angle, BorderStyle, Outline, Shadow, Alignment, "); addBuilder("MarginL, MarginR, MarginV, Encoding"); addBuilder("Style: Fix,Microsoft YaHei UI,45,&H66FFFFFF,&H66FFFFFF,&H66000000,&H66000000,1,0,0,0,100,100,0,0,1,2,0,2,20,20,2,0"); addBuilder("Style: R2L,Microsoft YaHei UI,45,&H66FFFFFF,&H66FFFFFF,&H66000000,&H66000000,1,0,0,0,100,100,0,0,1,2,0,2,20,20,2,0"); addBuilder(""); addBuilder("[Events]"); addBuilder("Format: Layer, Start, End, Style, Name, MarginL, MarginR, MarginV, Effect, Text"); } /** * 保存弹幕文件 * @param savePath 存储路径 * @return 存储结果 */ public boolean saveDanmu(String savePath) { System.out.println("savePath = " + savePath); File file = new File(savePath); try { if (file.exists()) { if (!file.delete()) { return false; } } boolean mkdirs = file.mkdirs(); boolean delete = file.delete(); if (!mkdirs || !delete) { return false; } if (!file.createNewFile()) { return false; } FileWriter writer = new FileWriter(file); writer.write(builder.toString()); writer.flush(); writer.close(); return true; } catch (IOException e) { e.printStackTrace(); } return false; } /** * 添加弹幕 * @param danmuData 弹幕 */ public void addDanmu(DanmuData danmuData) { if (filters.contains(danmuData.getDanmu())) { return; } addY(); long _time = (danmuData.getTime() - startTime.getTime()); long h = TimeUnit.MILLISECONDS.toHours(_time); long m = TimeUnit.MILLISECONDS.toMinutes(_time) % 60; long s = TimeUnit.MILLISECONDS.toSeconds(_time) % 60; String sTime = String.format("%s:%s:%s.0", new DecimalFormat("00").format(h), new DecimalFormat("00").format(m), new DecimalFormat("00").format(s)); if (s >= 52) { s = (s + 8) - 60; m++; } else { s += 8; } String eTime = String.format("%s:%s:%s.0", new DecimalFormat("00").format(h), new DecimalFormat("00").format(m), new DecimalFormat("00").format(s)); float x1, x2; x1 = 1920 + (danmuData.getDanmu().length() * 12.5f); x2 = 0 - (danmuData.getDanmu().length() * 12.5f); String ass = String.format("Dialogue: 0,%s,%s,R2L,,20,20,2,,{\\move(%.1f,%d,%.1f,%d)\\c&%s\\alpha&H%s}%s", sTime, eTime, x1, y, x2, y, danmuData.getFontColorHex(), alpha, danmuData.getDanmu() ); addBuilder(ass); } private void addY() { y += 30; if (y >= 1080) { y = 30; } } }