justadudewhohacks/face-api.js

Fetching external videos in browser (fetchImage for <video>)

Open

#392 opened on Aug 24, 2019

View on GitHub
 (11 comments) (4 reactions) (0 assignees)TypeScript (15,839 stars) (3,649 forks)batch import
enhancementgood first issuehelp wanted

Description

I've ran into this issue for a couple hours and I ended up editing the dist library adding two new functions called fetchVideo and bufferToVideo that works pretty much like the fetchImage and bufferToImage functions.

I'll leave it here to help somebody else with the same issue and in case someone wants to include it on future releases.

face-api.js

...
exports.fetchVideo = fetchVideo;
...
function fetchVideo(uri) {
        return __awaiter(this, void 0, void 0, function () {
            var res, blob;
            return __generator(this, function (_a) {
                switch (_a.label) {
                    case 0: return [4 /*yield*/, fetchOrThrow(uri)];
                    case 1:
                        res = _a.sent();
                        return [4 /*yield*/, (res).blob()];
                    case 2:
                        blob = _a.sent();
                        if (!blob.type.startsWith('video/')) {
                            throw new Error("fetchVideo - expected blob type to be of type video/*, instead have: " + blob.type + ", for url: " + res.url);
                        }
                        return [2 /*return*/, bufferToVideo(blob)];
                }
            });
        });
    }

function bufferToVideo(buf) {
        return new Promise(function (resolve, reject) {
            if (!(buf instanceof Blob)) {
                return reject('bufferToVideo - expected buf to be of type: Blob');
            }
            var reader = new FileReader();
            reader.onload = function () {
                if (typeof reader.result !== 'string') {
                    return reject('bufferToVideo - expected reader.result to be a string, in onload');
                }
                var video = env.getEnv().createVideoElement();
                video.onloadstart = function () {
                    setTimeout(() => {
                        return resolve(video);
                    }, 100)
                };
                video.onerror = reject;
                video.type = "video/mp4";
                video.autoplay = true;
                video.src = reader.result;
            };
            reader.onerror = reject;
            reader.readAsDataURL(buf);
        });
    }

Usage example:

const videoElement = document.querySelector('video');
    const detections = await faceapi
      .detectAllFaces(await faceapi.fetchVideo(videoElement.src))
      .withFaceLandmarks()
      .withFaceDescriptors();

Contributor guide