(
videoPath: string, videoFPS: number,
callback: (video: HTMLVideoElement, timestamp: number) =>
Promise<Keypoint[]>,
expected: number[][][], skeletonAdjacentPairs: number[][],
simulatedInterval: number)
| 83 | } |
| 84 | |
| 85 | export async function loadVideo( |
| 86 | videoPath: string, videoFPS: number, |
| 87 | callback: (video: HTMLVideoElement, timestamp: number) => |
| 88 | Promise<Keypoint[]>, |
| 89 | expected: number[][][], skeletonAdjacentPairs: number[][], |
| 90 | simulatedInterval: number): Promise<HTMLVideoElement> { |
| 91 | // We override video's timestamp with a fake timestamp. |
| 92 | let simulatedTimestamp: number; |
| 93 | // We keep a pointer for the expected array. |
| 94 | let idx: number; |
| 95 | |
| 96 | const actualInterval = 1 / videoFPS; |
| 97 | |
| 98 | // Create a video element on the html page and serve the content through karma |
| 99 | const video = document.createElement('video'); |
| 100 | // Hide video, and use canvas to render the video, so that we can also |
| 101 | // overlay keypoints. |
| 102 | video.style.visibility = 'hidden'; |
| 103 | const source = document.createElement('source'); |
| 104 | source.src = `${KARMA_SERVER}/${videoPath}`; |
| 105 | source.type = 'video/mp4'; |
| 106 | video.appendChild(source); |
| 107 | document.body.appendChild(video); |
| 108 | const canvas = document.createElement('canvas'); |
| 109 | canvas.style.position = 'absolute'; |
| 110 | canvas.style.left = '0'; |
| 111 | canvas.style.top = '0'; |
| 112 | document.body.appendChild(canvas); |
| 113 | const ctx = canvas.getContext('2d'); |
| 114 | |
| 115 | const promise = new Promise<HTMLVideoElement>((resolve, reject) => { |
| 116 | video.onseeked = async () => { |
| 117 | const keypoints = await callback(video, simulatedTimestamp); |
| 118 | |
| 119 | const expectedKeypoints = expected[idx].map(([x, y]) => { |
| 120 | return {x, y}; |
| 121 | }); |
| 122 | |
| 123 | ctx.drawImage(video, 0, 0); |
| 124 | draw(expectedKeypoints, ctx, skeletonAdjacentPairs, 'Green'); |
| 125 | |
| 126 | draw(keypoints, ctx, skeletonAdjacentPairs, 'Red'); |
| 127 | |
| 128 | const nextTime = video.currentTime + actualInterval; |
| 129 | if (nextTime < video.duration) { |
| 130 | video.currentTime = nextTime; |
| 131 | simulatedTimestamp += simulatedInterval; |
| 132 | idx++; |
| 133 | } else { |
| 134 | resolve(video); |
| 135 | } |
| 136 | }; |
| 137 | }); |
| 138 | |
| 139 | video.onloadedmetadata = () => { |
| 140 | video.currentTime = 0.001; |
| 141 | simulatedTimestamp = 0; |
| 142 | idx = 0; |
no test coverage detected