8. 精彩时刻全量相册
功能介绍

精彩时刻全量相册主要包含以下内容:
- 1.精彩时刻全量视频片段展示;
- 2.支持视频下载、AI 编辑、删除;
获取精彩时刻全量相册数据
相关代码段
import {
Button,
View,
showToast,
showModal,
albumFileDelete,
albumVideoFileList,
} from "@ray-js/ray";
import { useBatchDecryptImage } from "@/features";
import { deleteImages } from "@ray-js/ray-ipc-decrypt-image";
const { timeAlbumId, stockId, secret, onShow, homeId } = props;
const batchLoadInstance = useBatchDecryptImage(true, 400);
const getPageData = (params) => {
return new Promise((resolve, reject) => {
if (isNaN(Number(timeAlbumId)) || isNaN(Number(stockId))) {
showToast({ title: I18n.t("request.param.error") });
return;
}
const param: IAlbumVideoFileListReq = {
stockId: Number(stockId), // 库存id
gid: homeId, // 家庭id
timeAlbumId: Number(timeAlbumId), // 相册id
pageNum: params.page,
// 为了避免
endTime: endTimeRef.current,
// endTime: 1740386449,
pageSize: params.pageSize,
};
albumVideoFileList(param).then((result: IAlbumVideoFileListRes) => {
if (result && result.list && result.list.length > 0) {
const res = result.list.map((item) => {
const fileUrl = item.coverInfo?.fileUrl || "";
const fileName = fileUrl.split("?")[0].split("/").pop();
batchLoadInstance.addOriginData({
fileUrl,
decryptKey: secret,
});
return {
...item,
coverInfo: { ...item.coverInfo, ...{ fileName } },
};
});
batchLoadInstance.loadAllOriginData();
resolve({ data: res, total: result.total });
return;
}
resolve({ data: [] });
});
});
};
下载、合并、删除精彩时刻全量相册视频
相关代码段
import {
Button,
View,
showToast,
showModal,
albumFileDelete,
albumVideoFileList,
} from '@ray-js/ray'
import {
cancelVideoDownload,
composeVideos,
getAuthorize,
imageDownload,
videoDownload,
} from '@/features/downloadImage'
import { jumpToAiVideoEdit, jumpToPlayer } from '@/features/jump-to-page'
const [selectedIds, setSelectedIds] = useImmer([])
const [selectIdIndexMap, setSelectIdIndexMap] = useState<Map<number, number>>(new Map())
const getSelectDatas = () => {
const maxCount = selectedIds.length
let currentCount = 0
const result = []
for (let i = 0; i < cloudData.length; i++) {
if (currentCount >= maxCount) break
const item = cloudData[i]
const index = selectedIds.indexOf(item.id)
if (index >= 0) {
result[index] = item
currentCount++
}
}
return result
}
const onOperateCompose = async (e, type) => {
if (type === EOperate.download) {
isCloseDownload.current = false
if (selectedIds.length > MAX_DOWNLOAD_SIZE) {
showToast({
title: I18n.format('download.count.limit.desc', { time: MAX_DOWNLOAD_SIZE }),
icon: 'error',
})
return
}
const selectDatas = getSelectDatas()
const bl = await getAuthorize()
if (bl) {
onShow({ show: true, title: I18n.t('downloading.video'), type: ELoadingType.loading })
const indexErrs = []
// 下载一个成功后,再去下载另一个
for (let i = 0; i < selectDatas.length; i++) {
if (isCloseDownload.current) {
break
}
const ele = selectDatas[i]
if (ele.type === 1 || ele.type === 2) {
const dl = await videoDownload(deviceId, ele.mediaInfo?.fileUrl, secret)
if (dl === -1) {
indexErrs.push(i)
}
} else if (ele.type === 0) {
// 视频不存在,就下载图片
const dl = await imageDownload(deviceId, ele.coverInfo?.fileUrl, secret)
if (dl === -1) {
indexErrs.push(i)
}
} else {
indexErrs.push(i) // 说明云端返回类型不对
}
}
onShow({ show: false, title: I18n.t('download.success'), type: ELoadingType.success })
if (indexErrs.length > 0) {
const str = indexErrs.join(',')
showModal({
title: '',
content: str + I18n.t('download.clip.error'),
showCancel: false,
confirmText: I18n.t('common.confirm'),
})
} else {
setSelectedIds([])
setSelectIdIndexMap(null)
}
}
} else if (type === EOperate.compose) {
if (selectedIds.length > MAX_COMPOSE_SIZE) {
showToast({
title: I18n.format('compose.count.limit.desc', { time: MAX_COMPOSE_SIZE }),
icon: 'error',
})
return
}
const selectDatas = getSelectDatas()
const isVideos = isExistSingleImage(selectDatas)
if (isVideos) {
showToast({ title: I18n.t('compose.only.media'), icon: 'error' })
return
}
const bl = await getAuthorize()
if (bl) {
const mediaInfos = selectDatas.map((item) => {
return {
fileUrl: item.mediaInfo?.fileUrl || '',
key: secret,
}
})
const json = JSON.stringify({ fileInfo: mediaInfos })
onShow({ show: true, title: I18n.t('composing.video'), type: ELoadingType.loading })
const result = await composeVideos(deviceId, json)
if (result === -1) {
onShow({ show: false, title: I18n.t('compose.fail'), type: ELoadingType.error })
} else {
onShow({ show: false, title: I18n.t('compose.success'), type: ELoadingType.success })
setSelectedIds([])
setSelectIdIndexMap(null)
const { path = '', thingfilePath = '' } = result as Record<string, any>
setTimeout(() => {
jumpToAiVideoEdit({ videoPath: thingfilePath, videoOriginPath: path })
}, 0)
}
}
} else if (type === EOperate.delete) {
if (isNaN(Number(stockId))) {
showToast({ title: I18n.t('request.param.error') })
return
}
if (selectedIds.length > MAX_DELETE_SIZE) {
showToast({
title: I18n.format('delete.count.limit.desc', { time: MAX_DELETE_SIZE }),
icon: 'error',
})
return
}
showModal({
title: '',
content: I18n.t('module.delete.desc'),
cancelText: I18n.t('common.cancel'),
confirmText: I18n.t('aiVisual.delete'),
success: async ({ confirm, cancel }) => {
console.log('res===1', confirm, cancel)
if (confirm) {
const param: IAlbumFileDeleteReq = {
stockId: Number(stockId),
gid: homeId,
timeAlbumId: Number(timeAlbumId),
albumRecordIds: selectedIds.join(','),
}
const result = await albumFileDelete(param)
if (result) {
showToast({ title: I18n.t('aiVisual.delete.success'), icon: 'success' })
const curCloudDatas = getCurCloudDatas()
const selectDatas = curCloudDatas.filter((item) => selectedIds.includes(item.id))
const fileNames = selectDatas.map((item) => item.coverInfo.fileName)
deleteImages(deviceId, fileNames)
setDeletedIds([...new Set([...deletedIds, ...selectedIds])])
setSelectedIds([])
setSelectIdIndexMap(null)
} else {
showToast({ title: I18n.t('aiVisual.delete.fail'), icon: 'error' })
}
}
},
})
}
}
9. AI 二次编辑
功能介绍

精彩时刻视频 AI 编辑主要包含以下内容:
- 视频主体突出 AI 编辑;
- 视频隐私保护 AI 编辑;
视频主体突出 AI 编辑相关开发信息,可参考 AI 视频流主体突出功能模版。
视频隐私保护 AI 编辑
相关代码段
import { ai } from "@ray-js/ray";
import { createTempVideoRoot } from "@/utils";
const {
objectDetectCreate,
objectDetectDestroy,
objectDetectForVideo,
objectDetectForVideoCancel,
offVideoObjectDetectProgress,
onVideoObjectDetectProgress,
} = ai;
// 当前 AI 视频的编辑状态
const [handleState, setHandleState] = useState("idle");
// 当前 AI 视频流处理进度
const [progressState, setProgressState] = useState(0);
// 注册 App AI 实例
useEffect(() => {
objectDetectCreate();
return () => {
// 页面销毁时同时销毁 App AI 实例
objectDetectDestroy();
audioManager.destroy({
success: (res) => {
console.log("==destroy2==success", res);
},
fail: (error) => {
console.log("==destroy2==fail", error);
},
});
};
}, []);
// AI 视频流处理功能
const handleVideoByAI = (
detectType: number,
imageEditType: number,
musicPath = ""
) => {
const tempVideoPath = createTempVideoRoot();
onVideoObjectDetectProgress(handleListenerProgress);
privacyProtectDetectForVideo({
inputVideoPath: videoOriginSrc,
outputVideoPath: tempVideoPath,
detectType,
musicPath,
originAudioVolume: volumeObj.video / 100,
overlayAudioVolume: volumeObj.music / 100,
imageEditType,
audioEditType: 3,
success: ({ path }) => {
console.log("===path", path, tempVideoPath);
offVideoObjectDetectProgress(handleListenerProgress);
setProgressState(0);
fetchVideoThumbnails({
filePath: path,
startTime: 0,
endTime: 10,
thumbnailCount: 1,
thumbnailWidth: 375,
thumbnailHeight: 212,
success: (res) => {
console.log("===fetchVideoThumbnails==res", res);
setHandleState("success");
setVideoSrc(path);
setVideoOriginSrc(path);
setPosterSrc(res?.thumbnailsPath[0]);
showToast({
title: I18n.t("dsc_ai_generates_success"),
icon: "success",
});
},
fail: ({ errorMsg }) => {
console.log("==fetchVideoThumbnails==fail==", errorMsg);
},
});
},
fail: ({ errorMsg }) => {
console.log("==objectDetectForVideo==fail==", errorMsg);
offVideoObjectDetectProgress(handleListenerProgress);
setProgressState(0);
setHandleState("fail");
setHandleState("selectSkill");
setIsShowAISkills(true);
showToast({
title: I18n.t("dsc_ai_generates_fail"),
icon: "error",
});
},
});
};
// 打断 AI 隐私保护视频流生成
const handleCancelAIProcess = () => {
objectDetectForVideoCancel({
success: () => {
setHandleState("select");
},
});
};
具体 AI 技术方案介绍,详见:视频解决方案—IPC 精彩时刻通用方案
具体 API 相关介绍,详见:开发者文档—AI 基础包
10. 结束
- 恭喜你 🎉 完成了本教程的学习!
- 有任何问题可以提交工单咨询。
985

被折叠的 条评论
为什么被折叠?



