swtich to custom tfjs bundle

pull/50/head
Vladimir Mandic 2020-11-17 12:38:48 -05:00
parent 657c3cba03
commit 3c0dde0d6b
41 changed files with 37774 additions and 44174 deletions

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

View File

@ -30,7 +30,7 @@
"imports": []
},
"dist/human.esm.js": {
"bytes": 1837699,
"bytes": 1838222,
"imports": []
}
},
@ -38,14 +38,14 @@
"dist/demo-browser-index.js.map": {
"imports": [],
"inputs": {},
"bytes": 4813960
"bytes": 2997188
},
"dist/demo-browser-index.js": {
"imports": [],
"exports": [],
"inputs": {
"dist/human.esm.js": {
"bytesInOutput": 1830347
"bytesInOutput": 1831121
},
"demo/draw.js": {
"bytesInOutput": 7341
@ -60,7 +60,7 @@
"bytesInOutput": 17360
}
},
"bytes": 1882150
"bytes": 1882924
}
}
}

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

View File

@ -4,15 +4,19 @@
"bytes": 8721,
"imports": []
},
"dist/tfjs.esm.js": {
"bytes": 1586281,
"imports": []
},
"package.json": {
"bytes": 2021,
"imports": []
},
"src/age/age.js": {
"bytes": 1953,
"bytes": 1967,
"imports": [
{
"path": "src/tf.js"
"path": "dist/tfjs.esm.js"
},
{
"path": "src/profile.js"
@ -61,18 +65,18 @@
"imports": []
},
"src/body/modelBase.js": {
"bytes": 874,
"bytes": 888,
"imports": [
{
"path": "src/tf.js"
"path": "dist/tfjs.esm.js"
}
]
},
"src/body/modelMobileNet.js": {
"bytes": 584,
"bytes": 598,
"imports": [
{
"path": "src/tf.js"
"path": "dist/tfjs.esm.js"
},
{
"path": "src/body/modelBase.js"
@ -80,10 +84,10 @@
]
},
"src/body/modelPoseNet.js": {
"bytes": 1913,
"bytes": 1927,
"imports": [
{
"path": "src/tf.js"
"path": "dist/tfjs.esm.js"
},
{
"path": "src/body/modelMobileNet.js"
@ -133,10 +137,10 @@
]
},
"src/embedding/embedding.js": {
"bytes": 2092,
"bytes": 2106,
"imports": [
{
"path": "src/tf.js"
"path": "dist/tfjs.esm.js"
},
{
"path": "src/profile.js"
@ -144,10 +148,10 @@
]
},
"src/emotion/emotion.js": {
"bytes": 2991,
"bytes": 3005,
"imports": [
{
"path": "src/tf.js"
"path": "dist/tfjs.esm.js"
},
{
"path": "src/profile.js"
@ -155,18 +159,18 @@
]
},
"src/face/blazeface.js": {
"bytes": 6928,
"bytes": 6942,
"imports": [
{
"path": "src/tf.js"
"path": "dist/tfjs.esm.js"
}
]
},
"src/face/box.js": {
"bytes": 1920,
"bytes": 1934,
"imports": [
{
"path": "src/tf.js"
"path": "dist/tfjs.esm.js"
}
]
},
@ -175,10 +179,10 @@
"imports": []
},
"src/face/facemesh.js": {
"bytes": 2461,
"bytes": 2475,
"imports": [
{
"path": "src/tf.js"
"path": "dist/tfjs.esm.js"
},
{
"path": "src/face/blazeface.js"
@ -192,10 +196,10 @@
]
},
"src/face/facepipeline.js": {
"bytes": 13788,
"bytes": 13802,
"imports": [
{
"path": "src/tf.js"
"path": "dist/tfjs.esm.js"
},
{
"path": "src/face/box.js"
@ -213,10 +217,10 @@
"imports": []
},
"src/gender/gender.js": {
"bytes": 3394,
"bytes": 3408,
"imports": [
{
"path": "src/tf.js"
"path": "dist/tfjs.esm.js"
},
{
"path": "src/profile.js"
@ -232,18 +236,18 @@
"imports": []
},
"src/hand/box.js": {
"bytes": 3211,
"bytes": 3225,
"imports": [
{
"path": "src/tf.js"
"path": "dist/tfjs.esm.js"
}
]
},
"src/hand/handdetector.js": {
"bytes": 4221,
"bytes": 4235,
"imports": [
{
"path": "src/tf.js"
"path": "dist/tfjs.esm.js"
},
{
"path": "src/hand/box.js"
@ -251,10 +255,10 @@
]
},
"src/hand/handpipeline.js": {
"bytes": 7558,
"bytes": 7572,
"imports": [
{
"path": "src/tf.js"
"path": "dist/tfjs.esm.js"
},
{
"path": "src/hand/box.js"
@ -265,10 +269,10 @@
]
},
"src/hand/handpose.js": {
"bytes": 3020,
"bytes": 3034,
"imports": [
{
"path": "src/tf.js"
"path": "dist/tfjs.esm.js"
},
{
"path": "src/hand/handdetector.js"
@ -286,10 +290,10 @@
"imports": []
},
"src/human.js": {
"bytes": 15690,
"bytes": 15702,
"imports": [
{
"path": "src/tf.js"
"path": "dist/tfjs.esm.js"
},
{
"path": "src/face/facemesh.js"
@ -330,10 +334,10 @@
]
},
"src/image.js": {
"bytes": 5688,
"bytes": 5700,
"imports": [
{
"path": "src/tf.js"
"path": "dist/tfjs.esm.js"
},
{
"path": "src/imagefx.js"
@ -347,17 +351,13 @@
"src/profile.js": {
"bytes": 1061,
"imports": []
},
"src/tf.js": {
"bytes": 200,
"imports": []
}
},
"outputs": {
"dist/human.esm-nobundle.js.map": {
"imports": [],
"inputs": {},
"bytes": 669648
"bytes": 2912224
},
"dist/human.esm-nobundle.js": {
"imports": [],
@ -366,10 +366,10 @@
],
"inputs": {
"src/face/blazeface.js": {
"bytesInOutput": 5448
"bytesInOutput": 5797
},
"src/face/box.js": {
"bytesInOutput": 1666
"bytesInOutput": 1677
},
"src/face/util.js": {
"bytesInOutput": 2480
@ -378,34 +378,34 @@
"bytesInOutput": 30878
},
"src/face/facepipeline.js": {
"bytesInOutput": 9779
"bytesInOutput": 9895
},
"src/face/facemesh.js": {
"bytesInOutput": 1944
"bytesInOutput": 1983
},
"src/profile.js": {
"bytesInOutput": 895
"bytesInOutput": 897
},
"src/age/age.js": {
"bytesInOutput": 1212
"bytesInOutput": 1271
},
"src/gender/gender.js": {
"bytesInOutput": 2032
"bytesInOutput": 2157
},
"src/emotion/emotion.js": {
"bytesInOutput": 1884
"bytesInOutput": 2001
},
"src/embedding/embedding.js": {
"bytesInOutput": 1404
"bytesInOutput": 1452
},
"src/body/modelBase.js": {
"bytesInOutput": 640
"bytesInOutput": 655
},
"src/body/modelMobileNet.js": {
"bytesInOutput": 387
"bytesInOutput": 411
},
"src/body/heapSort.js": {
"bytesInOutput": 1145
"bytesInOutput": 1147
},
"src/body/buildParts.js": {
"bytesInOutput": 1353
@ -414,7 +414,7 @@
"bytesInOutput": 1822
},
"src/body/vectors.js": {
"bytesInOutput": 1079
"bytesInOutput": 1095
},
"src/body/decodePose.js": {
"bytesInOutput": 3229
@ -423,55 +423,55 @@
"bytesInOutput": 1732
},
"src/body/util.js": {
"bytesInOutput": 1955
"bytesInOutput": 1958
},
"src/body/modelPoseNet.js": {
"bytesInOutput": 1671
"bytesInOutput": 1686
},
"src/body/posenet.js": {
"bytesInOutput": 863
},
"src/hand/handdetector.js": {
"bytesInOutput": 2929
"bytesInOutput": 3234
},
"src/hand/handpipeline.js": {
"bytesInOutput": 4885
"bytesInOutput": 4912
},
"src/hand/anchors.js": {
"bytesInOutput": 127037
},
"src/hand/handpose.js": {
"bytesInOutput": 1831
"bytesInOutput": 1855
},
"src/gesture.js": {
"bytesInOutput": 2328
},
"src/imagefx.js": {
"bytesInOutput": 13872
"bytesInOutput": 13892
},
"src/image.js": {
"bytesInOutput": 4061
"bytesInOutput": 4143
},
"src/tf.js": {
"bytesInOutput": 115
"dist/tfjs.esm.js": {
"bytesInOutput": 1579998
},
"src/human.js": {
"bytesInOutput": 10588
"bytesInOutput": 10836
},
"src/hand/box.js": {
"bytesInOutput": 1979
"bytesInOutput": 1990
},
"src/hand/util.js": {
"bytesInOutput": 1854
"bytesInOutput": 1860
},
"config.js": {
"bytesInOutput": 1431
},
"package.json": {
"bytesInOutput": 20
"bytesInOutput": 21
}
},
"bytes": 250170
"bytes": 1838231
}
}
}

24
dist/human.esm.js vendored

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

21219
dist/human.esm.json vendored

File diff suppressed because it is too large Load Diff

24
dist/human.js vendored

File diff suppressed because one or more lines are too long

6
dist/human.js.map vendored

File diff suppressed because one or more lines are too long

21203
dist/human.json vendored

File diff suppressed because it is too large Load Diff

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

View File

@ -4,15 +4,19 @@
"bytes": 8721,
"imports": []
},
"dist/tfjs.esm.js": {
"bytes": 1586281,
"imports": []
},
"package.json": {
"bytes": 2021,
"imports": []
},
"src/age/age.js": {
"bytes": 1953,
"bytes": 1967,
"imports": [
{
"path": "src/tf.js"
"path": "dist/tfjs.esm.js"
},
{
"path": "src/profile.js"
@ -61,18 +65,18 @@
"imports": []
},
"src/body/modelBase.js": {
"bytes": 874,
"bytes": 888,
"imports": [
{
"path": "src/tf.js"
"path": "dist/tfjs.esm.js"
}
]
},
"src/body/modelMobileNet.js": {
"bytes": 584,
"bytes": 598,
"imports": [
{
"path": "src/tf.js"
"path": "dist/tfjs.esm.js"
},
{
"path": "src/body/modelBase.js"
@ -80,10 +84,10 @@
]
},
"src/body/modelPoseNet.js": {
"bytes": 1913,
"bytes": 1927,
"imports": [
{
"path": "src/tf.js"
"path": "dist/tfjs.esm.js"
},
{
"path": "src/body/modelMobileNet.js"
@ -133,10 +137,10 @@
]
},
"src/embedding/embedding.js": {
"bytes": 2092,
"bytes": 2106,
"imports": [
{
"path": "src/tf.js"
"path": "dist/tfjs.esm.js"
},
{
"path": "src/profile.js"
@ -144,10 +148,10 @@
]
},
"src/emotion/emotion.js": {
"bytes": 2991,
"bytes": 3005,
"imports": [
{
"path": "src/tf.js"
"path": "dist/tfjs.esm.js"
},
{
"path": "src/profile.js"
@ -155,18 +159,18 @@
]
},
"src/face/blazeface.js": {
"bytes": 6928,
"bytes": 6942,
"imports": [
{
"path": "src/tf.js"
"path": "dist/tfjs.esm.js"
}
]
},
"src/face/box.js": {
"bytes": 1920,
"bytes": 1934,
"imports": [
{
"path": "src/tf.js"
"path": "dist/tfjs.esm.js"
}
]
},
@ -175,10 +179,10 @@
"imports": []
},
"src/face/facemesh.js": {
"bytes": 2461,
"bytes": 2475,
"imports": [
{
"path": "src/tf.js"
"path": "dist/tfjs.esm.js"
},
{
"path": "src/face/blazeface.js"
@ -192,10 +196,10 @@
]
},
"src/face/facepipeline.js": {
"bytes": 13788,
"bytes": 13802,
"imports": [
{
"path": "src/tf.js"
"path": "dist/tfjs.esm.js"
},
{
"path": "src/face/box.js"
@ -213,10 +217,10 @@
"imports": []
},
"src/gender/gender.js": {
"bytes": 3394,
"bytes": 3408,
"imports": [
{
"path": "src/tf.js"
"path": "dist/tfjs.esm.js"
},
{
"path": "src/profile.js"
@ -232,18 +236,18 @@
"imports": []
},
"src/hand/box.js": {
"bytes": 3211,
"bytes": 3225,
"imports": [
{
"path": "src/tf.js"
"path": "dist/tfjs.esm.js"
}
]
},
"src/hand/handdetector.js": {
"bytes": 4221,
"bytes": 4235,
"imports": [
{
"path": "src/tf.js"
"path": "dist/tfjs.esm.js"
},
{
"path": "src/hand/box.js"
@ -251,10 +255,10 @@
]
},
"src/hand/handpipeline.js": {
"bytes": 7558,
"bytes": 7572,
"imports": [
{
"path": "src/tf.js"
"path": "dist/tfjs.esm.js"
},
{
"path": "src/hand/box.js"
@ -265,10 +269,10 @@
]
},
"src/hand/handpose.js": {
"bytes": 3020,
"bytes": 3034,
"imports": [
{
"path": "src/tf.js"
"path": "dist/tfjs.esm.js"
},
{
"path": "src/hand/handdetector.js"
@ -286,10 +290,10 @@
"imports": []
},
"src/human.js": {
"bytes": 15690,
"bytes": 15702,
"imports": [
{
"path": "src/tf.js"
"path": "dist/tfjs.esm.js"
},
{
"path": "src/face/facemesh.js"
@ -330,10 +334,10 @@
]
},
"src/image.js": {
"bytes": 5688,
"bytes": 5700,
"imports": [
{
"path": "src/tf.js"
"path": "dist/tfjs.esm.js"
},
{
"path": "src/imagefx.js"
@ -347,27 +351,23 @@
"src/profile.js": {
"bytes": 1061,
"imports": []
},
"src/tf.js": {
"bytes": 200,
"imports": []
}
},
"outputs": {
"dist/human.node-nobundle.js.map": {
"imports": [],
"inputs": {},
"bytes": 685808
"bytes": 2928376
},
"dist/human.node-nobundle.js": {
"imports": [],
"exports": [],
"inputs": {
"src/face/blazeface.js": {
"bytesInOutput": 5452
"bytesInOutput": 5801
},
"src/face/box.js": {
"bytesInOutput": 1673
"bytesInOutput": 1684
},
"src/face/util.js": {
"bytesInOutput": 2491
@ -376,34 +376,34 @@
"bytesInOutput": 30889
},
"src/face/facepipeline.js": {
"bytesInOutput": 9781
"bytesInOutput": 9897
},
"src/face/facemesh.js": {
"bytesInOutput": 1948
"bytesInOutput": 1987
},
"src/profile.js": {
"bytesInOutput": 897
"bytesInOutput": 899
},
"src/age/age.js": {
"bytesInOutput": 1215
"bytesInOutput": 1274
},
"src/gender/gender.js": {
"bytesInOutput": 2035
"bytesInOutput": 2160
},
"src/emotion/emotion.js": {
"bytesInOutput": 1887
"bytesInOutput": 2004
},
"src/embedding/embedding.js": {
"bytesInOutput": 1408
"bytesInOutput": 1456
},
"src/body/modelBase.js": {
"bytesInOutput": 642
"bytesInOutput": 657
},
"src/body/modelMobileNet.js": {
"bytesInOutput": 389
"bytesInOutput": 413
},
"src/body/heapSort.js": {
"bytesInOutput": 1147
"bytesInOutput": 1149
},
"src/body/buildParts.js": {
"bytesInOutput": 1355
@ -412,7 +412,7 @@
"bytesInOutput": 1833
},
"src/body/vectors.js": {
"bytesInOutput": 1087
"bytesInOutput": 1103
},
"src/body/decodePose.js": {
"bytesInOutput": 3231
@ -421,55 +421,55 @@
"bytesInOutput": 1734
},
"src/body/util.js": {
"bytesInOutput": 1963
"bytesInOutput": 1966
},
"src/body/modelPoseNet.js": {
"bytesInOutput": 1674
"bytesInOutput": 1689
},
"src/body/posenet.js": {
"bytesInOutput": 877
},
"src/hand/handdetector.js": {
"bytesInOutput": 2931
"bytesInOutput": 3236
},
"src/hand/handpipeline.js": {
"bytesInOutput": 4887
"bytesInOutput": 4914
},
"src/hand/anchors.js": {
"bytesInOutput": 127039
},
"src/hand/handpose.js": {
"bytesInOutput": 1834
"bytesInOutput": 1858
},
"src/gesture.js": {
"bytesInOutput": 2332
},
"src/imagefx.js": {
"bytesInOutput": 13874
"bytesInOutput": 13894
},
"src/image.js": {
"bytesInOutput": 4063
"bytesInOutput": 4145
},
"src/human.js": {
"bytesInOutput": 10626
"bytesInOutput": 10874
},
"src/tf.js": {
"bytesInOutput": 141
"dist/tfjs.esm.js": {
"bytesInOutput": 1580213
},
"src/hand/box.js": {
"bytesInOutput": 1979
"bytesInOutput": 1990
},
"src/hand/util.js": {
"bytesInOutput": 1854
"bytesInOutput": 1860
},
"config.js": {
"bytesInOutput": 1431
},
"package.json": {
"bytesInOutput": 20
"bytesInOutput": 21
}
},
"bytes": 250483
"bytes": 1838736
}
}
}

3960
dist/human.node.js vendored

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

1742
dist/human.node.json vendored

File diff suppressed because it is too large Load Diff

4092
dist/tfjs.esm.js vendored Normal file

File diff suppressed because one or more lines are too long

7
dist/tfjs.esm.js.map vendored Normal file

File diff suppressed because one or more lines are too long

21072
dist/tfjs.esm.json vendored Normal file

File diff suppressed because it is too large Load Diff

View File

@ -1,5 +1,6 @@
#!/usr/bin/env -S node --trace-warnings
const fs = require('fs');
const esbuild = require('esbuild');
const log = require('@vladmandic/pilogger');
@ -15,6 +16,15 @@ const common = {
target: 'es2018',
};
const tfjs = {
platform: 'browser',
format: 'esm',
metafile: 'dist/tfjs.esm.json',
entryPoints: ['src/tf.js'],
outfile: 'dist/tfjs.esm.js',
external: ['fs', 'buffer', 'util'],
};
// all build targets
const config = {
iifeBundle: {
@ -67,16 +77,51 @@ const config = {
},
};
async function getStats(metafile) {
const stats = {};
if (!fs.existsSync(metafile)) return stats;
const data = fs.readFileSync(metafile);
const json = JSON.parse(data);
if (json && json.inputs && json.outputs) {
for (const [key, val] of Object.entries(json.inputs)) {
if (key.startsWith('node_modules')) {
stats.modules = (stats.modules || 0) + 1;
stats.moduleBytes = (stats.moduleBytes || 0) + val.bytes;
} else {
stats.imports = (stats.imports || 0) + 1;
stats.importBytes = (stats.importBytes || 0) + val.bytes;
}
}
const files = [];
for (const [key, val] of Object.entries(json.outputs)) {
if (!key.endsWith('.map')) {
// stats.outputs += 1;
files.push(key);
stats.outputBytes = (stats.outputBytes || 0) + val.bytes;
}
}
stats.outputFiles = files.join(', ');
}
return stats;
}
// rebuild on file change
async function build(f, msg) {
log.info('Build: file', msg, f);
log.info('Build: file', msg, f, 'target:', common.target);
if (!es) es = await esbuild.startService();
// common build options
try {
// rebuild tfjs
if (f.endsWith('tf.js') || !module.parent) {
await es.build({ ...common, ...tfjs });
const stats = await getStats(tfjs.metafile);
log.state('Build:', stats);
}
// rebuild all targets
for (const [target, options] of Object.entries(config)) {
await es.build({ ...common, ...options });
log.state('Build complete:', target);
const stats = await getStats(options.metafile, target);
log.state('Build:', stats);
}
if (!module.parent) process.exit(0);
} catch (err) {

View File

@ -1,4 +1,4 @@
import { tf } from '../tf.js';
import { tf } from '../../dist/tfjs.esm.js';
import * as profile from '../profile.js';
const models = {};

View File

@ -1,4 +1,4 @@
import { tf } from '../tf.js';
import { tf } from '../../dist/tfjs.esm.js';
import * as kpt from './keypoints';
function getPointsConfidence(heatmapScores, heatMapCoords) {

View File

@ -1,4 +1,4 @@
import { tf } from '../tf.js';
import { tf } from '../../dist/tfjs.esm.js';
class BaseModel {
constructor(model, outputStride) {

View File

@ -1,4 +1,4 @@
import { tf } from '../tf.js';
import { tf } from '../../dist/tfjs.esm.js';
import * as modelBase from './modelBase';
class MobileNet extends modelBase.BaseModel {

View File

@ -1,4 +1,4 @@
import { tf } from '../tf.js';
import { tf } from '../../dist/tfjs.esm.js';
import * as modelMobileNet from './modelMobileNet';
import * as decodeMultiple from './decodeMultiple';
import * as util from './util';

View File

@ -1,4 +1,4 @@
import { tf } from '../tf.js';
import { tf } from '../../dist/tfjs.esm.js';
import * as profile from '../profile.js';
// based on https://github.com/sirius-ai/MobileFaceNet_TF

View File

@ -1,4 +1,4 @@
import { tf } from '../tf.js';
import { tf } from '../../dist/tfjs.esm.js';
import * as profile from '../profile.js';
const annotations = ['angry', 'disgust', 'fear', 'happy', 'sad', 'surpise', 'neutral'];

View File

@ -1,4 +1,4 @@
import { tf } from '../tf.js';
import { tf } from '../../dist/tfjs.esm.js';
const NUM_LANDMARKS = 6;

View File

@ -1,4 +1,4 @@
import { tf } from '../tf.js';
import { tf } from '../../dist/tfjs.esm.js';
function scaleBoxCoordinates(box, factor) {
const startPoint = [box.startPoint[0] * factor[0], box.startPoint[1] * factor[1]];

View File

@ -1,4 +1,4 @@
import { tf } from '../tf.js';
import { tf } from '../../dist/tfjs.esm.js';
import * as blazeface from './blazeface.js';
import * as pipe from './facepipeline.js';
import * as coords from './coords.js';

View File

@ -1,5 +1,5 @@
/* eslint-disable class-methods-use-this */
import { tf } from '../tf.js';
import { tf } from '../../dist/tfjs.esm.js';
import * as bounding from './box';
import * as util from './util';
import * as coords from './coords.js';

View File

@ -1,4 +1,4 @@
import { tf } from '../tf.js';
import { tf } from '../../dist/tfjs.esm.js';
import * as profile from '../profile.js';
const models = {};

View File

@ -14,7 +14,7 @@
* limitations under the License.
* =============================================================================
*/
import { tf } from '../tf.js';
import { tf } from '../../dist/tfjs.esm.js';
function getBoxSize(box) {
return [

View File

@ -15,7 +15,7 @@
* =============================================================================
*/
import { tf } from '../tf.js';
import { tf } from '../../dist/tfjs.esm.js';
import * as box from './box';
class HandDetector {

View File

@ -15,7 +15,7 @@
* =============================================================================
*/
import { tf } from '../tf.js';
import { tf } from '../../dist/tfjs.esm.js';
import * as box from './box';
import * as util from './util';

View File

@ -16,7 +16,7 @@
*/
// https://storage.googleapis.com/tfjs-models/demos/handpose/index.html
import { tf } from '../tf.js';
import { tf } from '../../dist/tfjs.esm.js';
import * as handdetector from './handdetector';
import * as pipeline from './handpipeline';
import * as anchors from './anchors';

View File

@ -1,4 +1,4 @@
import { tf, wasm } from './tf.js';
import { tf, wasm } from '../dist/tfjs.esm.js';
import * as facemesh from './face/facemesh.js';
import * as age from './age/age.js';
import * as gender from './gender/gender.js';

View File

@ -1,4 +1,4 @@
import { tf } from './tf.js';
import { tf } from '../dist/tfjs.esm.js';
import * as fxImage from './imagefx.js';
// internal temp canvases

2
wiki

@ -1 +1 @@
Subproject commit 86775430d497ec4c35f3703267cd273d16498179
Subproject commit 66b2c0f895189f0dda2ef2edc76fe81bbefecc9d