Unity启动,录制视频没有文件产出
This commit is contained in:
@@ -55,7 +55,7 @@ type CompositionInputSets = {
|
||||
|
||||
type VideoTimelineSegment = {
|
||||
startMs: number;
|
||||
endMs: number;
|
||||
endMs: number | null;
|
||||
activeInputs: ServerTrackRecordingFile[];
|
||||
};
|
||||
|
||||
@@ -275,8 +275,10 @@ function getVideoTimelineSegments(
|
||||
}
|
||||
|
||||
const activeInputs = sortActiveVideoInputs(files.filter((file) => {
|
||||
const inputStartMs = getInputStartMs(file) || timelineOriginMs;
|
||||
const inputEndMs = getInputEndMs(file) || timelineEndMs;
|
||||
const fileStartMs = getInputStartMs(file);
|
||||
const fileEndMs = getInputEndMs(file);
|
||||
const inputStartMs = fileStartMs === null ? timelineOriginMs : fileStartMs;
|
||||
const inputEndMs = fileEndMs === null ? timelineEndMs : fileEndMs;
|
||||
return inputStartMs < endMs && inputEndMs > startMs;
|
||||
}));
|
||||
segments.push({ startMs, endMs, activeInputs });
|
||||
@@ -285,6 +287,17 @@ function getVideoTimelineSegments(
|
||||
return segments;
|
||||
}
|
||||
|
||||
function getFallbackVideoTimelineSegment(
|
||||
files: ServerTrackRecordingFile[],
|
||||
timelineOriginMs: number | null
|
||||
): VideoTimelineSegment {
|
||||
return {
|
||||
startMs: timelineOriginMs === null ? 0 : timelineOriginMs,
|
||||
endMs: null,
|
||||
activeInputs: sortActiveVideoInputs(files)
|
||||
};
|
||||
}
|
||||
|
||||
export function buildFfmpegCompositionArgs(input: {
|
||||
videoInputs: ServerTrackRecordingFile[];
|
||||
audioInputs: ServerTrackRecordingFile[];
|
||||
@@ -299,7 +312,10 @@ export function buildFfmpegCompositionArgs(input: {
|
||||
const timelineOriginMs = getTimelineOriginMs(videoInputs.concat(input.audioInputs));
|
||||
const timelineEndMs = getTimelineEndMs(videoInputs.concat(input.audioInputs));
|
||||
const timelineDurationSeconds = getTimelineDurationSeconds(videoInputs.concat(input.audioInputs), timelineOriginMs);
|
||||
const videoSegments = getVideoTimelineSegments(videoInputs, timelineOriginMs, timelineEndMs);
|
||||
const timelineVideoSegments = getVideoTimelineSegments(videoInputs, timelineOriginMs, timelineEndMs);
|
||||
const videoSegments = timelineVideoSegments.length > 0
|
||||
? timelineVideoSegments
|
||||
: [getFallbackVideoTimelineSegment(videoInputs, timelineOriginMs)];
|
||||
const args = ['-y'];
|
||||
const orderedInputs = videoInputs.concat(input.audioInputs);
|
||||
orderedInputs.forEach((file) => {
|
||||
@@ -322,8 +338,11 @@ export function buildFfmpegCompositionArgs(input: {
|
||||
});
|
||||
|
||||
videoSegments.forEach((segment, segmentIndex) => {
|
||||
const segmentDurationSeconds = (segment.endMs - segment.startMs) / 1000;
|
||||
const segmentDurationSeconds = segment.endMs === null ? null : (segment.endMs - segment.startMs) / 1000;
|
||||
if (segment.activeInputs.length === 0) {
|
||||
if (segmentDurationSeconds === null) {
|
||||
return;
|
||||
}
|
||||
filters.push(`color=color=black:size=${outputWidth}x${outputHeight}:rate=30:duration=${formatSeconds(segmentDurationSeconds)},format=yuv420p[seg${segmentIndex}]`);
|
||||
return;
|
||||
}
|
||||
@@ -333,7 +352,8 @@ export function buildFfmpegCompositionArgs(input: {
|
||||
const inputLabel = videoInputUseCounts[inputIndex] > 1
|
||||
? `vin${inputIndex}_${videoInputUsePositions[inputIndex]++}`
|
||||
: `${inputIndex}:v`;
|
||||
const inputStartMs = getInputStartMs(file) || segment.startMs;
|
||||
const fileStartMs = getInputStartMs(file);
|
||||
const inputStartMs = fileStartMs === null ? segment.startMs : fileStartMs;
|
||||
const trimStartSeconds = Math.max(0, (segment.startMs - inputStartMs) / 1000);
|
||||
const width = segment.activeInputs.length === 1
|
||||
? outputWidth
|
||||
@@ -341,7 +361,11 @@ export function buildFfmpegCompositionArgs(input: {
|
||||
const height = segment.activeInputs.length === 1
|
||||
? outputHeight
|
||||
: activeIndex === 0 ? hostHeight : bottomHeight;
|
||||
filters.push(`[${inputLabel}]trim=start=${formatSeconds(trimStartSeconds)}:duration=${formatSeconds(segmentDurationSeconds)},setpts=PTS-STARTPTS,scale=${width}:${height}:force_original_aspect_ratio=decrease,pad=${width}:${height}:(ow-iw)/2:(oh-ih)/2:black,setsar=1[seg${segmentIndex}v${activeIndex}]`);
|
||||
const trimOptions = [`start=${formatSeconds(trimStartSeconds)}`];
|
||||
if (segmentDurationSeconds !== null) {
|
||||
trimOptions.push(`duration=${formatSeconds(segmentDurationSeconds)}`);
|
||||
}
|
||||
filters.push(`[${inputLabel}]trim=${trimOptions.join(':')},setpts=PTS-STARTPTS,scale=${width}:${height}:force_original_aspect_ratio=decrease,pad=${width}:${height}:(ow-iw)/2:(oh-ih)/2:black,setsar=1[seg${segmentIndex}v${activeIndex}]`);
|
||||
});
|
||||
|
||||
if (segment.activeInputs.length === 1) {
|
||||
@@ -435,6 +459,16 @@ function toOutput(job: RecordingCompositionJob, target: ServerTrackRecordingTarg
|
||||
};
|
||||
}
|
||||
|
||||
function getActiveCompositionJob(input: StartCompositionInput): RecordingCompositionJob | null {
|
||||
const recordingId = normalizeOption(input.recordingId, '');
|
||||
const meetingId = normalizeOption(input.meetingId, '');
|
||||
return Array.from(jobs.values()).find((job) => {
|
||||
return job.recordingId === recordingId
|
||||
&& job.meetingId === meetingId
|
||||
&& (job.status === 'queued' || job.status === 'running');
|
||||
}) || null;
|
||||
}
|
||||
|
||||
async function runRecordingCompositionJob(job: RecordingCompositionJob): Promise<RecordingCompositionJob> {
|
||||
const timestamp = nowIso();
|
||||
job.status = 'running';
|
||||
@@ -489,6 +523,11 @@ async function runRecordingCompositionJob(job: RecordingCompositionJob): Promise
|
||||
}
|
||||
|
||||
export function startRecordingCompositionJob(input: StartCompositionInput): RecordingCompositionJob {
|
||||
const activeJob = getActiveCompositionJob(input);
|
||||
if (activeJob) {
|
||||
return activeJob;
|
||||
}
|
||||
|
||||
const timestamp = nowIso();
|
||||
const inputSets = getInputSets(input);
|
||||
const job: RecordingCompositionJob = {
|
||||
|
||||
Reference in New Issue
Block a user