json2srt:剪映字幕 json 转 srt

2021-05-26  本文已影响0人  佛分_知合

这是一个命令行 js 程序,需要安装 node

Windows 平台:剪映 1.2.1 测试通过
macOS:剪映 1.3.1 测试通过

用法

0. 首先,当然是要下载本库的 json2srt.js 这个程序。
1. 第一步,在「剪映 Pro」软件中,自动生成字幕
2. 第二步,进入命令行。

此工具需要带一个参数,即 json 文件所处的目录名称。

Windows 上,剪映字幕的工作目录是:USER_HOME + '\AppData\Local\JianyingPro\User Data\Projects\com.lveditor.draft';

macOS 上,剪映字幕的工作目录是:USER_HOME + '/Movies/JianyingPro/User Data/Projects/com.lveditor.draft/'

在命令行上,执行:

node json2srt.js <json 文件所在的目录名>

如果不知道「json 文件所在的目录名」,可以不带参数执行:

node json2srt.js

命令会提示你到哪个目录下去找。

生成的 srt 文件在那里?

生成的 srt 文件,和 json 文件在同一个目录。

命令执行成功时,会把生成的 srt 文件路径打印在屏幕上。

json2srt.js 源码:

// 这个命令行工具,是根据 https://pansong291.gitee.io/web/html/tool/JianyingPro.html 修改而来
// 感谢原作者!
// 修改者:知合
// 2021-05-26
// 南无阿弥陀佛🙏🏻



const os = require('os');
const fs = require('fs')

// 获取 home 目录
const USER_HOME = process.env.HOME || process.env.USERPROFILE
const RN = '\r';

// 当前字幕文件的目录(从命令行读取)
jsonFolder = process.argv.slice(2);

// 剪映的工作目录(macOS)
if (os.platform() == 'darwin') { //macOS 的路径
   jianyingPath = USER_HOME + '/Movies/JianyingPro/User Data/Projects/com.lveditor.draft/';
   
   // 剪映生成的字幕 json 文件
   jsonFile = jianyingPath + jsonFolder + '/draft_info.json';
   // 程序将生成的 srt 文件
   srtFile = jianyingPath + jsonFolder + '/draft_info.srt';
   // 换行符
   let RN = '\r';
} else { // Windows 的路径
   jianyingPath = USER_HOME + '\\AppData\\Local\\JianyingPro\\User Data\\Projects\\com.lveditor.draft\\';
   // 剪映生成的字幕 json 文件
   jsonFile = jianyingPath + jsonFolder + '/draft.json';
   // 程序将生成的 srt 文件
   srtFile = jianyingPath + jsonFolder + '/draft.srt';
   // 换行符
   let RN = '\r\n';
}

try {
   if (jsonFolder.length == 0) {
       console.log('请提供 json 目录。\n');
       console.log('请到 ' + jianyingPath + ' 目录下找。\n\n');
       console.log('如果目录名为 AFA473B4-BB11-4D6D-98AC-4A0E039A13D6,则请执行:');
       console.log('node json2srt.js AFA473B4-BB11-4D6D-98AC-4A0E039A13D6\n');
       return;
   }
   // 读取 json 文件
   let  inputText= fs.readFileSync(jsonFile);

   let temp;
   // 剪映 json 对象
   temp = JSON.parse(inputText);
   
   let srtFiles = convertJSON2SRT(temp);
   console.log('生成完毕:'+ srtFile);
} catch (e) {
   console.log('JSON 解析错误:'+e);
}


function convertJSON2SRT(jy) {
   // 平台系统
   let os = jy.platform.os;
   // 提取文本材料
   // Map 结构 = {id1: text1, id2: text2, ...}
   let texts = {}, temp = jy.materials.texts;
   for (let i in temp) {
       texts[temp[i].id] = temp[i].content;
   }

    // 轨道列表
   let tracks = jy.tracks, track;
   // SRT 文件 Map
   let srtFiles = {};
   for (let i in tracks) {
       track = tracks[i];
       temp = convertTrack2Srt(track, texts, os);
       if (temp) {
           srtFiles[track.id] = temp;
       }
   }
   return srtFiles;
}

/**
* 将一条轨道转换为 srt 文本
* @param track 轨道
* @param texts 文本材料
* @param milli 是否是毫秒单位
* @return {string}
*/
function convertTrack2Srt(track, texts, milli) {
   let segments = track.segments, segment;
   let srt = {content: null, start: null, end: null};
   let srtText = '', index = 0;
   for (let i in segments) {
       segment = segments[i];
       srt.content = texts[segment.material_id];
       if (!srt.content) continue;
       srt.start = segment.target_timerange.start;
       srt.end = srt.start + segment.target_timerange.duration;
       srt.start = getSrtTimeText(srt.start, milli);
       srt.end = getSrtTimeText(srt.end, milli);
       index++;
       srtText += formatSrt(index, srt);
   }
   fs.writeFile(srtFile, srtText, function (err) {
       if (err) {
           return console.error(err);
       } 
   });
}

/**
* 获取 SRT 格式的时间文本
* @param time 时间,windows版本为微秒数
* @param milli 是否是毫秒单位
* @returns {string}
*/
function getSrtTimeText(time, milli) {
   // 1h1m1s111ms = 61m1s111ms = 3661s111ms = 3661111ms
   if (!milli) {
       time = Math.floor(time / 1000);
   }
   // 余出的毫秒
   let millisecond = time % 1000;
   time = Math.floor(time / 1000);
   // 余出秒
   let second = time % 60;
   time = Math.floor(time / 60);
   // 余出分钟
   let minute = time % 60;
   time = Math.floor(time / 60);
   // 剩余时数
   let hour = time;
   hour = formatDigit(hour, 2);
   minute = formatDigit(minute, 2);
   second = formatDigit(second, 2);
   millisecond = formatDigit(millisecond, 3);
   return hour + ':' + minute + ':' + second + ',' + millisecond;
}

/**
* 格式化为 SRT
* @param index 字幕序号,从 1 开始
* @param srt 字幕内容等信息
* @returns {string}
*/
function formatSrt(index, srt) {
   return index + RN + srt.start + ' --> ' + srt.end + RN + srt.content + RN + RN;
}

/**
* 格式化数字   
* @param digit 数字
* @param length 长度
* @returns {string}
*/
function formatDigit(digit, length) {
   let str = digit.toString();
   while (str.length < length) {
       str = '0' + str;
   }
   return str;
}

上一篇下一篇

猜你喜欢

热点阅读