| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286 |
- import * as protobuf from './protobuf.js';
- const mediapipe = {};
- mediapipe.ModelFactory = class {
- async match(context) {
- const tags = await context.tags('pbtxt');
- if (tags.has('node') && ['input_stream', 'output_stream', 'input_side_packet', 'output_side_packet'].some((key) => tags.has(key) || tags.has(`node.${key}`))) {
- return context.set('mediapipe.pbtxt');
- }
- return null;
- }
- async open(context) {
- // mediapipe.proto = await context.require('./mediapipe-proto');
- mediapipe.proto = {};
- let config = null;
- try {
- const reader = await context.read('protobuf.text');
- // const config = mediapipe.proto.mediapipe.CalculatorGraphConfig.decodeText(reader);
- config = new mediapipe.Object(reader);
- } catch (error) {
- const message = error && error.message ? error.message : error.toString();
- throw new mediapipe.Error(`File text format is not mediapipe.CalculatorGraphConfig (${message.replace(/\.$/, '')}).`);
- }
- return new mediapipe.Model(config);
- }
- };
- mediapipe.Model = class {
- constructor(config) {
- this.format = 'MediaPipe';
- this.modules = [new mediapipe.Graph(config)];
- }
- };
- mediapipe.Graph = class {
- constructor(config) {
- config = config || {};
- this.inputs = [];
- this.outputs = [];
- this.nodes = [];
- const types = new Map();
- const type = (list) => {
- if (!Array.isArray(list)) {
- list = list ? [list] : [];
- }
- return list.map((item) => {
- const parts = item.split(':');
- const name = parts.pop();
- const type = parts.join(':');
- if (!types.has(name)) {
- const value = new Set();
- if (type) {
- value.add(type);
- }
- types.set(name, value);
- } else if (type && !types.get(name).has(type)) {
- types.get(name).add(type);
- }
- return name;
- });
- };
- config.input_stream = type(config.input_stream);
- config.output_stream = type(config.output_stream);
- config.input_side_packet = type(config.input_side_packet);
- config.output_side_packet = type(config.output_side_packet);
- if (!Array.isArray(config.node)) {
- config.node = config.node ? [config.node] : [];
- }
- for (const node of config.node) {
- node.input_stream = type(node.input_stream);
- node.output_stream = type(node.output_stream);
- node.input_side_packet = type(node.input_side_packet);
- node.output_side_packet = type(node.output_side_packet);
- }
- const values = new Map();
- for (const [name, value] of types) {
- const type = Array.from(value).join(',');
- values.set(name, new mediapipe.Value(name, type || null));
- }
- const value = (name) => {
- return values.get(name);
- };
- for (const name of config.input_stream) {
- const argument = new mediapipe.Argument(name, [value(name)]);
- this.inputs.push(argument);
- }
- for (const name of config.output_stream) {
- const argument = new mediapipe.Argument(name, [value(name)]);
- this.outputs.push(argument);
- }
- for (const name of config.input_side_packet) {
- const argument = new mediapipe.Argument(name, [value(name, type)]);
- this.inputs.push(argument);
- }
- for (const output of config.output_side_packet) {
- const parts = output.split(':');
- const type = (parts.length > 1) ? parts.shift() : '';
- const name = parts.shift();
- const argument = new mediapipe.Argument(name, [value(name, type)]);
- this.outputs.push(argument);
- }
- for (const node of config.node) {
- this.nodes.push(new mediapipe.Node(node, value));
- }
- }
- };
- mediapipe.Node = class {
- constructor(node, value) {
- const type = node.calculator || '?';
- this.name = '';
- this.type = { name: type.replace(/Calculator$/, '') };
- this.inputs = [];
- this.outputs = [];
- this.attributes = [];
- if (node.input_stream) {
- const values = node.input_stream.map((name) => value(name));
- const argument = new mediapipe.Argument('input_stream', values);
- this.inputs.push(argument);
- }
- if (node.output_stream) {
- const values = node.output_stream.map((name) => value(name));
- this.outputs.push(new mediapipe.Argument('output_stream', values));
- }
- if (node.input_side_packet) {
- const values = node.input_side_packet.map((name) => value(name));
- this.inputs.push(new mediapipe.Argument('output_stream', values));
- }
- if (node.output_side_packet) {
- const values = node.output_side_packet.map((name) => value(name));
- this.outputs.push(new mediapipe.Argument('output_side_packet', values));
- }
- const options = new Map();
- if (node.options) {
- for (const key of Object.keys(node.options)) {
- options.set(key, node.options[key]);
- }
- }
- let node_options = node.node_options;
- if (!Array.isArray(node_options)) {
- node_options = node_options ? [node_options] : [];
- }
- if (mediapipe.proto.google && node_options.every((options) => options instanceof mediapipe.proto.google.protobuf.Any)) {
- for (const entry of node_options) {
- const value = new RegExp(/^\{(.*)\}\s*$/, 's').exec(entry.value);
- const buffer = new TextEncoder('utf-8').encode(value[1]);
- const reader = protobuf.TextReader.open(buffer);
- if (entry.type_url.startsWith('type.googleapis.com/mediapipe.')) {
- const type = entry.type_url.split('.').pop();
- if (mediapipe.proto && mediapipe.proto.mediapipe && mediapipe.proto.mediapipe[type]) {
- const message = mediapipe.proto.mediapipe[type].decodeText(reader);
- for (const key of Object.keys(message)) {
- options.set(key, message[key]);
- }
- continue;
- }
- }
- const message = new mediapipe.Object(reader);
- for (const [name, value] of Object.entries(message)) {
- options.set(name, value);
- }
- }
- } else {
- for (const option of node_options) {
- for (const [name, value] of Object.entries(option)) {
- if (name !== '__type__') {
- options.set(name, value);
- }
- }
- }
- }
- for (const [name, value] of options) {
- const attribute = new mediapipe.Argument(name, value);
- this.attributes.push(attribute);
- }
- }
- };
- mediapipe.Argument = class {
- constructor(name, value) {
- this.name = name;
- this.value = value;
- }
- };
- mediapipe.Value = class {
- constructor(name, type = null) {
- if (typeof name !== 'string') {
- throw new mediapipe.Error(`Invalid value identifier '${JSON.stringify(name)}'.`);
- }
- this.name = name;
- this.type = type;
- }
- };
- mediapipe.Object = class {
- constructor(reader, block) {
- if (!block) {
- reader.start();
- }
- const type = reader.token();
- if (type.startsWith('[') && type.endsWith(']')) {
- this.__type__ = type.substring(1, type.length - 1);
- reader.next();
- reader.match(':');
- reader.start();
- }
- const arrayTags = new Set();
- while (!reader.end()) {
- const tag = reader.tag();
- const next = reader.token();
- let obj = null;
- if (next === '{') {
- reader.start();
- obj = new mediapipe.Object(reader, true);
- if (obj.__type__) {
- while (!reader.end()) {
- if (!Array.isArray(obj)) {
- obj = [obj];
- }
- const token = reader.token();
- if (token.startsWith('[') && token.endsWith(']')) {
- obj.push(new mediapipe.Object(reader, true));
- continue;
- }
- break;
- }
- }
- } else if (next.startsWith('"') && next.endsWith('"')) {
- obj = next.substring(1, next.length - 1);
- reader.next();
- } else if (next === 'true' || next === 'false') {
- obj = next;
- reader.next();
- } else if (reader.first()) {
- obj = [];
- while (!reader.last()) {
- const data = reader.token();
- reader.next();
- if (!isNaN(data)) {
- obj.push(parseFloat(data));
- }
- }
- } else if (isNaN(next)) {
- obj = next;
- reader.next();
- } else {
- obj = parseFloat(next);
- reader.next();
- }
- if (this[tag] && (!Array.isArray(this[tag]) || arrayTags.has(tag))) {
- this[tag] = [this[tag]];
- arrayTags.delete(tag);
- }
- if (this[tag]) {
- this[tag].push(obj);
- } else {
- if (Array.isArray(obj)) {
- arrayTags.add(tag);
- }
- this[tag] = obj;
- }
- reader.match(',');
- }
- }
- };
- mediapipe.Error = class extends Error {
- constructor(message) {
- super(message);
- this.name = 'Error loading MediaPipe model.';
- }
- };
- export const ModelFactory = mediapipe.ModelFactory;
|