UNPKG

wranglebot

Version:

open source media asset management

234 lines (219 loc) 7.92 kB
class FilterMask { private readonly filters: any[]; readonly transform: Function; constructor(props: string[], transform: Function = (value) => value) { this.filters = props; this.transform = transform; } getFilters() { return this.filters; } } class Scraper { static EXTRACT_VIDEO = "video"; static EXTRACT_AUDIO = "audio"; static availableColumns = { /* SHOT */ video: [ { id: "scene", name: "Scene", mask: new FilterMask(["scene"]) }, { id: "shot", name: "Shot", mask: new FilterMask(["shot"]) }, { id: "take", name: "Take", mask: new FilterMask(["take"]) }, { id: "description", name: "Description", mask: new FilterMask(["description"]) }, { id: "comments", name: "Comments", mask: new FilterMask(["comments"]) }, { id: "keywords", name: "Keywords", mask: new FilterMask(["keywords"]) }, { id: "good-take", name: "Good Take", mask: new FilterMask(["good take"]) }, { id: "creation-date", name: "Creation Date", mask: new FilterMask(["creation_date", "creation_time", "encoded_date", "encoded_time", "modification_date", "modification_time"]), }, /* VIDEO TECHNICAL */ { id: "video-camera-index", name: "Camera Index", mask: new FilterMask(["com.arri.camera.CameraIndex"]), }, { id: "video-camera-id", name: "Camera Index", mask: new FilterMask(["com.arri.camera.CameraId"]), }, { id: "video-camera-sn", name: "Camera Serialnumber", mask: new FilterMask(["com.arri.camera.CameraSerialNumber"]), }, { id: "reel-name", name: "Reel Name", mask: new FilterMask(["com.arri.camera.ReelName", "tags.reel_name"]) }, { id: "video-start-tc", name: "Start TC", mask: new FilterMask(["timecode"]) }, { id: "video-frames", name: "Frames", mask: new FilterMask(["duration_ts"], (value) => { return parseInt(value); }), }, { id: "video-duration", name: "Duration", mask: new FilterMask(["duration"]) }, { id: "video-bit-depth", name: "Bit Depth", mask: new FilterMask(["bits_per_raw_sample"]) }, { id: "video-field-dominance", name: "Field Dominance", mask: new FilterMask(["field_order"]) }, { id: "video-width", name: "Width", mask: new FilterMask(["width"]) }, { id: "video-height", name: "Height", mask: new FilterMask(["height"]) }, { id: "video-aspect-ratio", name: "Aspect Ratio", mask: new FilterMask(["display_aspect_ratio"]) }, { id: "video-pixel-ratio", name: "Pixel Ratio", mask: new FilterMask(["sample_aspect_ratio"]) }, { id: "video-frame-rate", name: "Frame Rate", mask: new FilterMask(["r_frame_rate"], (value) => { const [numerator, denominator] = value.split("/"); return parseFloat(numerator) / parseFloat(denominator); }), }, { id: "video-bit-rate", name: "Bit Rate", mask: new FilterMask(["bit_rate"]) }, { id: "video-codec", name: "Codec", mask: new FilterMask(["codec_long_name"]) }, { id: "video-profile", name: "Profile", mask: new FilterMask(["profile"]) }, { id: "video-format", name: "Container", mask: new FilterMask(["format_long_name"]) }, /* VIDEO CREATIVE */ { id: "video-camera-model", name: "Camera Model", mask: new FilterMask(["com.arri.camera.CameraModel", "product_name"]), }, { id: "video-shutter-angle", name: "Shutter Angle", mask: new FilterMask(["com.arri.camera.ShutterAngle"]), }, { id: "video-white-balance-kelvin", name: "White Balance", mask: new FilterMask(["com.arri.camera.WhiteBalanceKelvin"]), }, { id: "white-balance-tint", name: "Tint", mask: new FilterMask(["com.arri.camera.WhiteBalanceTintCc"]), }, { id: "video-color-space", name: "Color Space", mask: new FilterMask(["color_space", "color_primaries"]), }, { id: "video-gamma", name: "Gamma Curve", mask: new FilterMask(["com.arri.camera.ColorGammaSxS"]), }, { id: "video-iso", name: "ISO", mask: new FilterMask(["com.arri.camera.ExposureIndexAsa"]) }, { id: "video-lut", name: "LUT", mask: new FilterMask(["com.arri.camera.look.name"]) }, { id: "video-neutral-density", name: "ND", mask: new FilterMask(["com.arri.camera.NdFilterDensity"]) }, { id: "video-camera-firmware", name: "Firmware", mask: new FilterMask(["com.arri.camera.SupVersion", "product_version"]), }, ], audio: [ { id: "audio-codec", name: "Audio Codec", mask: new FilterMask(["codec_long_name"]), }, { id: "audio-channels", name: "Audio Channels", mask: new FilterMask(["channels"]), }, { id: "audio-channel-positions", name: "Audio Channel Pos", mask: new FilterMask(["channel_positions"]), }, { id: "audio-sample-rate", name: "Audio Sample Rate", mask: new FilterMask(["sample_rate"]), }, { id: "audio-duration", name: "Audio Duration", mask: new FilterMask(["duration"]), }, { id: "audio-bit-rate", name: "Audio Bitrate", mask: new FilterMask(["bits_per_sample"]), }, ], }; private parsedMetaData = {}; static getColumnNames() { let list: any = []; for (let entry of Scraper.availableColumns.video) { list.push(entry.name); } for (let entry of Scraper.availableColumns.audio) { list.push(entry.name); } return list; } static getColumns() { let list: any = []; for (let entry of Scraper.availableColumns.video) { list.push({ id: entry.id, name: entry.name, filters: entry.mask.getFilters(), }); } for (let entry of Scraper.availableColumns.audio) { list.push({ id: entry.id, name: entry.name, filters: entry.mask.getFilters(), }); } return list; } private extract(extractor, entry, rawMetaData) { if (entry.mask) { for (let mask of entry.mask.getFilters()) { if (extractor === Scraper.EXTRACT_VIDEO) { for (let [key, value] of Object.entries(rawMetaData)) { if (key === mask) { if (value === "N/A" || value === "unknown") return undefined; return entry.mask.transform(value); } } } else if (extractor === Scraper.EXTRACT_AUDIO) { for (let [key, value] of Object.entries(rawMetaData)) { if (value === "N/A" || value === "unknown") return undefined; if (key === mask) return entry.mask.transform(value); } } } return undefined; } } parse(raw) { if (!raw.streams) return {}; if (raw.streams.length === 0) throw new Error("No streams found in metadata"); let videoStream = raw.streams.find((stream) => stream.codec_type === "video"); let audioStreams = raw.streams.filter((stream) => stream.codec_type === "audio"); let format = raw.format; let tags = format.tags; for (let entry of Scraper.availableColumns.video) { this.parsedMetaData[entry.id] = this.extract(Scraper.EXTRACT_VIDEO, entry, videoStream) || this.extract(Scraper.EXTRACT_VIDEO, entry, format) || this.extract(Scraper.EXTRACT_VIDEO, entry, tags) || ""; } for (let entry of Scraper.availableColumns.audio) { for (let audioStream of audioStreams) { this.parsedMetaData[entry.id] = this.extract(Scraper.EXTRACT_AUDIO, entry, audioStream) || ""; } } return this.parsedMetaData; } } export default new Scraper(); export { Scraper };