UNPKG

mp4filechecker

Version:

Check details of an mp4 file, e.g. to determine if transcoding is required

146 lines (145 loc) 4.48 kB
"use strict"; Object.defineProperty(exports, "__esModule", { value: true }); function _export(target, all) { for(var name in all)Object.defineProperty(target, name, { enumerable: true, get: Object.getOwnPropertyDescriptor(all, name).get }); } _export(exports, { get DEFAULT_OPTIONS () { return DEFAULT_OPTIONS; }, get checkMp4File () { return checkMp4File; } }); const _mp4box = /*#__PURE__*/ _interop_require_wildcard(require("mp4box")); function _getRequireWildcardCache(nodeInterop) { if (typeof WeakMap !== "function") return null; var cacheBabelInterop = new WeakMap(); var cacheNodeInterop = new WeakMap(); return (_getRequireWildcardCache = function(nodeInterop) { return nodeInterop ? cacheNodeInterop : cacheBabelInterop; })(nodeInterop); } function _interop_require_wildcard(obj, nodeInterop) { if (!nodeInterop && obj && obj.__esModule) { return obj; } if (obj === null || typeof obj !== "object" && typeof obj !== "function") { return { default: obj }; } var cache = _getRequireWildcardCache(nodeInterop); if (cache && cache.has(obj)) { return cache.get(obj); } var newObj = { __proto__: null }; var hasPropertyDescriptor = Object.defineProperty && Object.getOwnPropertyDescriptor; for(var key in obj){ if (key !== "default" && Object.prototype.hasOwnProperty.call(obj, key)) { var desc = hasPropertyDescriptor ? Object.getOwnPropertyDescriptor(obj, key) : null; if (desc && (desc.get || desc.set)) { Object.defineProperty(newObj, key, desc); } else { newObj[key] = obj[key]; } } } newObj.default = obj; if (cache) { cache.set(obj, newObj); } return newObj; } const DEFAULT_OPTIONS = { maxWidth: 1280, maxHeight: 720, supportedMimeTypes: [ 'video/mp4' ], supportedVideoCodecs: [ /^avc1\.42e0/, /^avc1\.4d40/, /^avc1\.6400/ ], supportedAudioCodecs: [ 'mp4a.40.2', 'mp4a.40.5' ] }; const loadBuffer = (blob)=>new Promise(function(resolve, reject) { const fileReader = new FileReader(); fileReader.onload = function(evt) { if (!evt.target) { reject(new Error('File could not be read')); } else if (evt.target.error) { reject(evt.target.error); } else { resolve(evt.target.result); } }; fileReader.readAsArrayBuffer(blob); }); async function* loadChunks(file, chunkSize = 64 * 1024) { const fileSize = file.size; let offset = 0; while(offset <= fileSize){ const chunkBlob = file.slice(offset, chunkSize + offset); const chunkData = await loadBuffer(chunkBlob); chunkData.fileStart = offset; yield chunkData; offset += chunkData.byteLength; } } const matchesOne = (candidateValue, testValues)=>{ return testValues.some((testCase)=>{ if (testCase instanceof RegExp) { return testCase.test(candidateValue); } else { return candidateValue === testCase; } }); }; const isMatch = (info, options)=>{ const tracks = info.tracks; return tracks.every((track)=>{ if (track.type === 'video') { const isSupportedCodec = matchesOne(track.codec, options.supportedVideoCodecs); const isSupportedWidth = track.video.width <= options.maxWidth; const isSupportedHeight = track.video.height <= options.maxHeight; return isSupportedCodec && isSupportedWidth && isSupportedHeight; } else if (track.type === 'audio') { return matchesOne(track.codec, options.supportedAudioCodecs); } else { return true; } }); }; const checkMp4File = async (file, options = DEFAULT_OPTIONS)=>{ if (!file || !matchesOne(file.type, options.supportedMimeTypes)) { return false; } const box = _mp4box.createFile(); let result = null; box.onReady = (info)=>{ result = info; }; for await (const chunk of loadChunks(file)){ box.appendBuffer(chunk); if (result) { break; } } if (result === null) { return false; } else { return isMatch(result, options); } };