import { define } from "../../define/define"; import path from "path"; import { Tools } from "../tools"; const { v4: uuidv4 } = require('uuid'); const fspromises = require("fs").promises; const mm = require('music-metadata'); const wavFileInfo = require('wav-file-info'); let tools = new Tools(); import { PublicMethod } from './publicMethod' import { cloneDeep } from "lodash"; const compressing = require("compressing"); export class ClipDraft { constructor(global, value, draftName = null) { this.speedId = null; this.canvasesId = null; this.soundChannelId = null; this.vocalSeparationsId = null; this.materialVideoId = null; this.tracksSegmentsId = null; this.trackTypeId = null; this.materialAnimationsId = null; this.materialsTextID = null; this.materialsBeatsID = null; this.textId = null; this.friendlyReminderId = null; this.draft_json = null; this.one_duration_time = 5000000; this.text_end_time = 0; this.iamge_end_time = 0; this.TTS_emd_time = 0; this.draft_duration_time = 0; this.global = global; this.value = value; this.pm = new PublicMethod(global); this.draft_name = draftName; } async InitData() { this.draft_name = this.draft_name ? this.draft_name : this.global.config.project_name + '_' + this.value[0]; let draft_path = path.join(this.global.config.draft_path, this.draft_name); await fspromises.rm(draft_path, { recursive: true, force: true }); await compressing.zip.uncompress(define.draft_temp_path, path.join(this.global.config.draft_path, this.global.config.project_name + '_' + this.value[0])); this.draftPath = path.join(draft_path, "draft_content.json"); this.image_dir = path.join(this.global.config.project_path, `tmp/${this.value[0]}`); this.srtPath = this.value[1].srt_path; this.style_id = this.value[1].draft_srt_style; this.num = 1; this.mp3_path = this.value[1].audio_path; this.friendlyReminderId = this.value[1].friendly_reminder; this.srt_information = (await this.pm.GetConfigJson(JSON.stringify(["srt_time_information", []]))).data; } /** * 加载默认的草稿 * @returns */ async LoadDraftJson() { let draft_json = JSON.parse(await fspromises.readFile(this.draftPath)); this.draft_json = draft_json; // console.log(this.draft_json); } /** * 添加speed */ async AddSpeeds() { // 获取speed的模板地址 let speed_json = JSON.parse(await fspromises.readFile(define.clip_speed_temp_path)); // console.log(speed_json) // 设置ID let speedID = uuidv4().toUpperCase(); this.speedId = speedID; speed_json.id = speedID; return speed_json; } /** * 添加Canvases */ async AddCanvases() { let canvases_json = JSON.parse(await fspromises.readFile(define.add_canvases_temp_path)); // console.log(canvases_json); // 设置ID let canvasesId = uuidv4().toUpperCase(); this.canvasesId = canvasesId; canvases_json.id = canvasesId; return canvases_json; } /** * 添加soundchannel * @returns */ async AddSoundChannelMapping() { let soundChannelMapping_json = JSON.parse(await fspromises.readFile(define.add_sound_channel_mappings_temp_path)); // console.log(soundChannelMapping_json) let sound_channel_mappings_tmp_ID = uuidv4().toUpperCase(); this.soundChannelId = sound_channel_mappings_tmp_ID; soundChannelMapping_json.id = sound_channel_mappings_tmp_ID; return soundChannelMapping_json; } /** * 添加 vocal_separations */ async AddVocalSeparations() { let vocal_separations_json = JSON.parse(await fspromises.readFile(define.add_vocal_separations_temp_path)); // console.log(vocal_separations_json); let vocalSeparationId = uuidv4().toUpperCase(); this.vocalSeparationsId = vocalSeparationId; vocal_separations_json.id = vocalSeparationId; return vocal_separations_json; } /** * 添加一个文件到原材料地址 * @param {图片文件地址} imagePath */ async AddMaterialVideo(imagePath) { let materialVideoTmpJson = JSON.parse(await fspromises.readFile(define.add_material_video_temp_path)); // console.log(materialVideoTmpJson); let materialId = uuidv4().toUpperCase(); this.materialVideoId = materialId; materialVideoTmpJson.id = materialId; // 获取输入的图片宽高 materialVideoTmpJson.width = 1000; materialVideoTmpJson.height = 1000; materialVideoTmpJson.path = imagePath; let image_name = path.basename(imagePath); materialVideoTmpJson.material_name = image_name; return materialVideoTmpJson; } /** * 添加一个轨道 * @returns */ async AddTracksSegments() { let tracksJson = JSON.parse(await fspromises.readFile(define.add_tracks_segments_temp_path)); // console.log(tracksJson); let tracksSegmentsId = uuidv4().toUpperCase(); tracksJson.id = tracksSegmentsId; tracksJson.extra_material_refs = []; tracksJson.extra_material_refs.push(this.speedId); tracksJson.extra_material_refs.push(this.canvasesId); tracksJson.extra_material_refs.push(this.soundChannelId); tracksJson.extra_material_refs.push(this.vocalSeparationsId); tracksJson.material_id = this.materialVideoId; tracksJson.target_timerange.start = this.num * tracksJson.target_timerange.duration; return tracksJson; } /** * 新建一个track * @param {track的类型} type */ async AddTracks(type) { let tracks_json = JSON.parse(await fspromises.readFile(define.add_tracks_type_temp_path)); let track_type_id = uuidv4(); this.trackTypeId = track_type_id; tracks_json.id = this.trackTypeId; tracks_json.type = type; return tracks_json; } /** * 添加单个图片到轨道 */ async AddOneImageToDraft(image_path) { // 添加 canvases let canvanses = await this.AddCanvases(); this.draft_json.materials.canvases.push(canvanses) // 添加 sound_channel_mappings let sound_channel = await this.AddSoundChannelMapping(); this.draft_json.materials.sound_channel_mappings.push(sound_channel) // 添加 speeds let speeds = await this.AddSpeeds(); this.draft_json.materials.speeds.push(speeds); // 添加 vocal_separations let vocal_sep = await this.AddVocalSeparations(); this.draft_json.materials.vocal_separations.push(vocal_sep); // 添加视频 materials 下面的 Videos let video = await this.AddMaterialVideo(image_path); this.draft_json.materials.videos.push(video); // 添加track轨道 let segment = await this.AddTracksSegments(); return segment; // this.draft_json.tracks.segments.push(segment); } /** * 将所有的文件全部都写轨道上面 */ async AddAllImageToTracks() { let img_dir = path.normalize(this.image_dir); let files = await fspromises.readdir(img_dir) let imageFiles = files.filter(file => /\.(png)$/i.test(file)); imageFiles.sort(); imageFiles = imageFiles.map(item => path.join(img_dir, item)) // console.log(imageFiles); // 创建一个tracks let tracks_json = await this.AddTracks("video"); //往tracks里面的segments添加图片数据 for (let i = 0; i < imageFiles.length; i++) { const image_path = imageFiles[i]; let segment = await this.AddOneImageToDraft(image_path); tracks_json.segments.push(segment); // console.log(tracks_json); } this.draft_json.tracks.push(tracks_json); // 修改持续时间 let duration_time = imageFiles.length * this.one_duration_time; this.iamge_end_time = duration_time; } /** * 添加materials中的material_animations */ async AddMaterialAnimations() { let material_animations = JSON.parse(await fspromises.readFile(define.add_material_animations_temp_path)); let material_animations_id = uuidv4(); this.materialAnimationsId = material_animations_id; material_animations.id = material_animations_id; return material_animations; } /** * 为字幕添加样式 */ async AddTextStyle(material_text_json) { try { let clip_setting = JSON.parse(await fspromises.readFile(define.clip_setting)); let text_style = clip_setting.text_style.filter(item => item.id != "0" && item.id != "1"); // 添加默认样式 let c = JSON.parse(material_text_json.content); let data = JSON.parse(`[{\"size\":7.882736,\"fill\":{\"content\":{\"solid\":{\"color\":[1,1,1]}}},\"range\":[0,5]}]`); data[0].range = [0, c.text.length]; c["styles"] = data; material_text_json.content = JSON.stringify(c); return material_text_json; // 判断是不是添加样式添加样式 if (this.style_id == "0") { return material_text_json; } else if (this.style_id == "1") { // 随机 const randomIndex = Math.floor(Math.random() * text_style.length); this.style_id = text_style[randomIndex].id; } let style = text_style.filter(item => item.id == this.style_id)[0]; let content = JSON.parse(material_text_json.content); // 修改范围 let textstring = content.text; let length = textstring.length; style.style[0].range = [0, length]; content.styles = style.style; material_text_json.content = JSON.stringify(content); let path = style.style[0].font.path; let id = style.style[0].font.id; let font_size = style.font_size; let fonts = style.fonts; let style_name = style.style_name; material_text_json.fonts.id = uuidv4(); material_text_json.font_category_id = id; material_text_json.fonts.path = path; material_text_json.fonts.title = fonts; material_text_json.check_flag = font_size; material_text_json.title = fonts; material_text_json.font_size = font_size; material_text_json.style_name = style_name; return material_text_json; } catch (error) { throw error; } } /** * 获得一个单的materialsText */ async AddMaterialsText(textString) { let material_text_json = JSON.parse(await fspromises.readFile(define.add_material_text_temp_path)); let material_text_id = uuidv4(); this.materialsTextID = material_text_id; material_text_json.id = material_text_id; // 设置内容 let content = JSON.parse(material_text_json.content); content.text = textString; material_text_json.content = JSON.stringify(content); material_text_json = await this.AddTextStyle(material_text_json); return material_text_json; } async ModifyTextClipTransform(text_segments) { // console.log(text_segments); let clip_setting = JSON.parse(await fspromises.readFile(define.clip_setting)); let text_style = clip_setting.text_style; if (text_style.length <= 0) return text_segments; let style = text_style.filter(item => item.id == this.style_id)[0]; text_segments.clip = style.clip; return text_segments; } /** * 添加一个字幕到tracks * @returns */ async AddOneTextToDraft(timeObj) { try { // 添加 materials 中的 material_animations let material_animattions = await this.AddMaterialAnimations(); this.draft_json.materials.material_animations.push(material_animattions); // 添加 materials 下面的texts let material_text = await this.AddMaterialsText(timeObj.text); this.draft_json.materials.texts.push(material_text); let text_segments = JSON.parse(await fspromises.readFile(define.add_track_text_segments_temp_path)); let textId = uuidv4(); this.textId = textId; text_segments.id = textId; text_segments.extra_material_refs = [this.materialAnimationsId]; text_segments.material_id = this.materialsTextID; text_segments.target_timerange.start = timeObj.start; text_segments.target_timerange.duration = timeObj.end - timeObj.start; // 修改样式偏移量 text_segments = await this.ModifyTextClipTransform(text_segments); return text_segments; } catch (error) { return { code: 0, message: `Error Message ${error}` } } } /** * 添加所有的text到tracks里面 */ async AddAllTextToTrack() { // 添加一个tracks let new_tracks = await this.AddTracks("text"); // 计算时间 let srt_data = (await fspromises.readFile(this.srtPath)).toString("utf-8"); const entries = srt_data.replace(/\r\n/g, '\n').split('\n\n'); let data = entries.map(entry => { const lines = entry.split('\n'); if (lines.length >= 3) { const times = lines[1]; const text = lines.slice(2).join(' '); const [start, end] = times.split(' --> ').map(time => { const [hours, minutes, seconds] = time.split(':'); const [sec, millis] = seconds.split(','); return ((parseInt(hours) * 3600 + parseInt(minutes) * 60 + parseInt(sec)) * 1000 + parseInt(millis)) * 1000; }); return { start, end, text }; } }).filter(entry => entry); for (let i = 0; i < data.length; i++) { const text = data[i]; let text_se = await this.AddOneTextToDraft(text); // console.log(text_se); new_tracks.segments.push(text_se); if (i == data.length - 1) { this.text_end_time = text.end; } } // console.log(this.draft_json) this.draft_json.tracks.push(new_tracks); } /** * 添加 materials下面的 beats */ async AddMaterialsBeats() { let beats_json = JSON.parse(await fspromises.readFile(define.add_materials_beats_tmp_path)); let materialsBeatsID = uuidv4(); this.materialsBeatsID = materialsBeatsID; beats_json.id = materialsBeatsID; return beats_json; } async getAudioDuration(filePath) { const ext = filePath.split('.').pop().toLowerCase(); switch (ext) { case 'mp3': try { const metadata = await mm.parseFile(filePath); return metadata.format.duration; } catch (error) { throw new Error(error); } case 'wav': return new Promise((resolve, reject) => { wavFileInfo.infoByFilename(filePath, (err, info) => { if (err) { reject(err); } else { resolve(info.duration); } }); }); default: throw new Error("不支持的文件类型"); } } /** * 添加 materials 下面的 audios */ async AddMaterialsAudios(musicPath) { try { let audios_json = JSON.parse(await fspromises.readFile(define.add_materials_audios_tmp_path)); let mp3_name = path.basename(musicPath); let time = await this.getAudioDuration(path.normalize(musicPath)); let duration_time = time * 1000000; if (this.audios_duration_time == undefined) { this.audios_duration_time = duration_time; } let audiosID = uuidv4(); this.materialsAudiosID = audiosID; audios_json.id = audiosID; audios_json.name = mp3_name; audios_json.duration = duration_time; audios_json.path = musicPath; console.log(audios_json) return audios_json; } catch (error) { throw new Error(error); } } /** * 添加tracks下面的audios下面的Segments */ async AddAudioTracksSegments() { try { let audio_segments = JSON.parse(await fspromises.readFile(define.add_tracks_audio_segments_tmp_path)); let audioId = uuidv4(); this.tracksAudioId = audioId; audio_segments.id = audioId; audio_segments.material_id = this.materialsAudiosID; audio_segments.extra_material_refs = []; audio_segments.extra_material_refs.push(this.speedID); audio_segments.extra_material_refs.push(this.materialsBeatsID); audio_segments.extra_material_refs.push(this.soundChannelId); audio_segments.extra_material_refs.push(this.vocalSeparationsId); audio_segments.source_timerange.duration = this.audios_duration_time; audio_segments.target_timerange.duration = this.audios_duration_time; return audio_segments; } catch (error) { throw new Error(error); } } /** * 添加配音 */ async AddTTSMusic(musicPath) { // 添加speeds let speeds = await this.AddSpeeds(); this.draft_json.materials.speeds.push(speeds); // 添加beats let beats = await this.AddMaterialsBeats(); this.draft_json.materials.beats.push(beats); // 添加 sound_channel_mappings let sound_channel_mappings = await this.AddSoundChannelMapping(); this.draft_json.materials.sound_channel_mappings.push(sound_channel_mappings) // 添加 materials 下面的 audios let audios = await this.AddMaterialsAudios(musicPath); this.draft_json.materials.audios.push(audios); // 添加一个track let tracks_json = await this.AddTracks("audio"); let audio_segments_json = await this.AddAudioTracksSegments(); tracks_json.segments.push(audio_segments_json); this.draft_json.tracks.push(tracks_json); } /** * 添加背景音乐 * @param {背景音乐的ID} background_music_id */ async AddRandomBackfroundMusic(background_music_id) { try { // 获取背景音乐文件夹 let clip_setting_json = JSON.parse(await fspromises.readFile(define.clip_setting)); let setting = clip_setting_json.background_music_setting.filter(item => item.id == background_music_id); console.log(setting); let folder_path = setting[0].folder_path; console.log(folder_path); let files = await tools.getFilesWithExtensions(folder_path, [".mp3", ".wav"]); if (files.length == 0) { throw new Error("背景音乐文件夹下面未存在数据"); } // 获取随机的数据 const randomIndex = Math.floor(Math.random() * files.length); let musicPath = files[randomIndex]; // 添加speeds let speeds = await this.AddSpeeds(); this.draft_json.materials.speeds.push(speeds); // 添加beats let beats = await this.AddMaterialsBeats(); this.draft_json.materials.beats.push(beats); // 添加 sound_channel_mappings let sound_channel_mappings = await this.AddSoundChannelMapping(); this.draft_json.materials.sound_channel_mappings.push(sound_channel_mappings) // 添加 materials 下面的 audios let audios = await this.AddMaterialsAudios(musicPath); // audios.duration = this.text_end_time; this.draft_json.materials.audios.push(audios); // 添加一个track let tracks_json = await this.AddTracks("audio"); let audio_segments_json = await this.AddAudioTracksSegments(); // 修改 audio_segments_json.source_timerange.duration = this.audios_duration_time; audio_segments_json.target_timerange.duration = this.audios_duration_time; tracks_json.segments.push(audio_segments_json); this.draft_json.tracks.push(tracks_json); } catch (error) { throw new Error(error); } } /** * 添加温馨提示 */ async AddFriendlyReminder() { // 直接push try { return; let friendlyReminder = null; let friendlyReminderSetting = JSON.parse(await fspromises.readFile(define.clip_setting)).friendly_reminder_setting; friendlyReminderSetting = friendlyReminderSetting.filter(item => item.id != "0" && item.id != "1"); if (friendlyReminderSetting.length <= 0) { return; } if (this.friendlyReminderId == "0") { return; } else if (this.friendlyReminderId == "1") { // 获取随机的数据 const randomIndex = Math.floor(Math.random() * friendlyReminderSetting.length); friendlyReminder = friendlyReminderSetting[randomIndex]; } else { friendlyReminder = friendlyReminderSetting.filter(item => item.id == this.friendlyReminderId); } // 添加 materials 下面的 material_animations this.draft_json.materials.material_animations.push(friendlyReminder.material_animations); // 添加 materials下面的texts this.draft_json.materials.texts.push(friendlyReminder.texts); // 添加 tracks let track = friendlyReminder.tracks; // 修改持续时间 track.segments[0].target_timerange.duration = this.audios_duration_time; this.draft_json.tracks.push(track); } catch (error) { throw new Error(error); } } /** * 修改草稿的持续时间 */ async ModifyDurationTime() { let max_time = Math.max(this.iamge_end_time, this.text_end_time, this.audios_duration_time); this.draft_json.duration = max_time; this.draft_json.canvas_config.height = 1440; this.draft_json.canvas_config.width = 1920; this.draft_json.canvas_config.ratio = "4:3"; } /** * 将文件写道指定的位置 */ async WriteDraftFile() { await fspromises.writeFile(this.draftPath, JSON.stringify(this.draft_json)); } async find_draft_node(nodes, type, value) { for (let index = 0; index < nodes.length; index++) { let node = nodes[index]; if (node[type] == value) { return node } } } /** * 将草稿图片和文字对齐 */ async AlginDraftImgToText() { // 所有的字幕轨道里面的数据,读取出来 let img_nodes = (await this.find_draft_node(this.draft_json.tracks, "type", "video")).segments; //将最后一个数据修改为背景音乐的最后时间 this.srt_information[this.srt_information.length - 1].end_time = this.audios_duration_time / 1000; // 开始对齐 for (let i = 0; i < this.srt_information.length; i++) { if (img_nodes.length < i) { break; } const element = this.srt_information[i]; let duration = 0; if (i + 1 < this.srt_information.length) { duration = (this.srt_information[i + 1].start_time - element.start_time - 1) * 1000; } else { duration = (element.end_time - element.start_time) * 1000; } img_nodes[i].source_timerange.duration = duration; img_nodes[i].target_timerange.duration = duration; img_nodes[i].target_timerange.start = element.start_time * 1000; } } /** * 通过 key_frame 返回关键帧数据 * @param {*} key_frame 关键帧配置 */ async GetFrameData(key_frame_key, key_frame) { if (key_frame_key == "KFTypePositionY") { return key_frame.up_down_key_frame; } else if (key_frame_key == "KFTypePositionX") { return key_frame.left_right_key_frame; } else if (key_frame_key == "KFTypeScale") { return key_frame.scale_key_frame; } else { return { "default_scale": 100, "start_position": 0, "end_position": 0 } } } /** * 图片添加关键帧 */ async AddKeyFarme() { let img_nodes = (await this.find_draft_node(this.draft_json.tracks, "type", "video")).segments; let key_frame_tmp_data = await fspromises.readFile(define.add_keyframe_tmp_path, "utf-8"); // 添加关键帧 // 将最后一个数据修改为背景音乐的最后时间 this.srt_information[this.srt_information.length - 1].end_time = this.audios_duration_time / 1000; let key_frame_setting = await tools.getJsonFilePropertyValue(define.clip_setting, "key_frame", null, false); // 判断关键帧配置是不是存在。不存在直接结束 if (key_frame_setting == null) { return; } let isFixedSpeed = key_frame_setting.isFixedSpeed; let isDown = true; // 获取通用的关键帧配置,然后添加到每一个图片上面(可以设置时间。当前图片的持续实现小于设置的时间。会计算不要过快) for (let i = 0; i < img_nodes.length; i++) { let element = img_nodes[i]; let image_duartion = cloneDeep(element.source_timerange.duration); let key_frame = key_frame_setting.key_frame; // 做随机处理 let real_key_frame = key_frame; let key_frame_list = ["KFTypePositionY", "KFTypePositionX", "KFTypeScale"]; if (key_frame == "KFTypeRandom") { // 随机获取 key_frame_list 里面的一个数据 const randomIndex = Math.floor(Math.random() * key_frame_list.length); real_key_frame = key_frame_list[randomIndex]; } let key_frame_pos = await this.GetFrameData(real_key_frame, key_frame_setting); let key_frame_time = key_frame_setting.key_frame_time * 1000000; let scale_rate = key_frame_pos.default_scale / 100; let up_pos = Math.abs(key_frame_pos.start_position); let down_pos = Math.abs(key_frame_pos.end_position); let key_frame_tmp = JSON.parse(key_frame_tmp_data) if (real_key_frame == "KFTypePositionY") { // 勾选了匀速。需要计算时间(计算比例) if (isFixedSpeed && image_duartion < key_frame_time) { let time_rate = image_duartion / key_frame_time; up_pos = up_pos * time_rate; down_pos = down_pos * time_rate; } let up_pos_rate = isDown ? (up_pos / this.draft_json.canvas_config.height) : (0 - up_pos / this.draft_json.canvas_config.height) key_frame_tmp.id = uuidv4(); key_frame_tmp.keyframe_list[0].id = uuidv4(); // Corrected assignment key_frame_tmp.keyframe_list[0].values = [up_pos_rate]; let dow_pos_rate = isDown ? (0 - down_pos / this.draft_json.canvas_config.height) : (down_pos / this.draft_json.canvas_config.height) key_frame_tmp.keyframe_list[1].id = uuidv4(); key_frame_tmp.keyframe_list[1].time_offset = image_duartion; key_frame_tmp.keyframe_list[1].values = [dow_pos_rate]; key_frame_tmp.property_type = real_key_frame; // 修改缩放倍率 element.clip.scale.x = scale_rate; element.clip.scale.y = scale_rate; element.clip.transform.y = dow_pos_rate; isDown = !isDown; } else if (real_key_frame == "KFTypePositionX") { // 勾选了匀速。需要计算时间(计算比例) if (isFixedSpeed && image_duartion < key_frame_time) { let time_rate = image_duartion / key_frame_time; up_pos = up_pos * time_rate; down_pos = down_pos * time_rate; } let up_pos_rate = isDown ? (up_pos / this.draft_json.canvas_config.width) : (0 - up_pos / this.draft_json.canvas_config.width) key_frame_tmp.id = uuidv4(); key_frame_tmp.keyframe_list[0].id == uuidv4(); key_frame_tmp.keyframe_list[0].values = [up_pos_rate]; let dow_pos_rate = isDown ? (0 - down_pos / this.draft_json.canvas_config.width) : (down_pos / this.draft_json.canvas_config.width) key_frame_tmp.keyframe_list[1].id = uuidv4(); key_frame_tmp.keyframe_list[1].time_offset = image_duartion; key_frame_tmp.keyframe_list[1].values = [dow_pos_rate]; key_frame_tmp.property_type = real_key_frame; // 修改缩放倍率 element.clip.scale.x = scale_rate; element.clip.scale.y = scale_rate; element.clip.transform.x = dow_pos_rate; isDown = !isDown; } else if (real_key_frame == "KFTypeScale") { if (isFixedSpeed && image_duartion < key_frame_time) { let time_rate = image_duartion / key_frame_time; // 计算方式和上面的不同 let sub_total = Math.abs(up_pos - down_pos); let currwnt_rate = sub_total * (1 - time_rate); up_pos = up_pos - (up_pos * (currwnt_rate / up_pos)) / 2; down_pos = down_pos + (down_pos * (currwnt_rate / down_pos)) / 2; } // 修改上面的数据,添加Y轴缩放 let up_pos_rate = isDown ? up_pos / 100 : down_pos / 100; key_frame_tmp.id = uuidv4(); key_frame_tmp.keyframe_list[0].id == uuidv4(); key_frame_tmp.keyframe_list[0].values = [up_pos_rate]; let dow_pos_rate = isDown ? down_pos / 100 : up_pos / 100; key_frame_tmp.keyframe_list[1].id = uuidv4(); key_frame_tmp.keyframe_list[1].time_offset = image_duartion; key_frame_tmp.keyframe_list[1].values = [dow_pos_rate]; key_frame_tmp.property_type = real_key_frame + "X"; // 修改上面的数据,添加Y轴缩放 // 修改缩放倍率 element.clip.scale.x = isDown ? up_pos : dow_pos_rate; element.clip.scale.y = isDown ? up_pos : dow_pos_rate; element.clip.transform.x = 0; element.common_keyframes.push(key_frame_tmp); key_frame_tmp = JSON.parse(JSON.stringify(key_frame_tmp)) key_frame_tmp.id = uuidv4(); key_frame_tmp.keyframe_list[0].id == uuidv4(); key_frame_tmp.keyframe_list[1].id = uuidv4(); key_frame_tmp.property_type = real_key_frame + "Y"; isDown = !isDown; } element.common_keyframes.push(key_frame_tmp); } } /** * 添加草稿 */ async addDraft() { try { await this.InitData(); await this.LoadDraftJson(); await this.AddAllImageToTracks(); await this.AddAllTextToTrack(); await this.AddTTSMusic(path.normalize(this.value[1].audio_path)); if (this.value[1].background_music != "" && this.value[1].background_music != undefined && this.value[1].background_music != null) { await this.AddRandomBackfroundMusic(this.value[1].background_music); } // 添加温馨提示 // await this.AddFriendlyReminder(); await this.ModifyDurationTime(); // 对齐草稿数据 await this.AlginDraftImgToText(); // 添加关键帧 await this.AddKeyFarme(); await this.WriteDraftFile(); return { code: 1, draft_name: this.draft_name } } catch (error) { return { code: 0, message: `An error occurred: ${error}` } } } }