yootd 0.0.63 → 0.0.65

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -1,3 +1,4 @@
1
1
  import React from 'react';
2
+ import './index.scss';
2
3
  import { DepartmentProps } from './types/types';
3
4
  export declare const Department: React.FC<DepartmentProps>;
@@ -4,8 +4,11 @@ import { useQuery } from '@tanstack/react-query';
4
4
  import React, { useMemo } from 'react';
5
5
  import { TreeSelect } from "./..";
6
6
  import { useRequest } from "../hooks/useRequest";
7
+ import { useBem } from "../hooks/useBem";
8
+ import "./index.scss";
7
9
  export var Department = function Department(_ref) {
8
10
  var rest = Object.assign({}, (_objectDestructuringEmpty(_ref), _ref));
11
+ var mb = useBem('department');
9
12
  var request = useRequest();
10
13
  // 查询所有部门
11
14
  var _useQuery = useQuery({
@@ -43,6 +46,7 @@ export var Department = function Department(_ref) {
43
46
  return treeNode === null || treeNode === void 0 || (_treeNode$title = treeNode.title) === null || _treeNode$title === void 0 ? void 0 : _treeNode$title.includes(inputValue);
44
47
  };
45
48
  return /*#__PURE__*/React.createElement(TreeSelect, _extends({}, rest, {
49
+ popupClassName: "".concat(mb),
46
50
  showSearch: true,
47
51
  treeData: deptTreeData,
48
52
  filterTreeNode: filterTreeNode
@@ -0,0 +1,6 @@
1
+ .yot-department {
2
+ .ant-select-tree-treenode {
3
+ margin-bottom: 0 !important;
4
+ padding-bottom: calc(var(--ant-padding-xs) / 2) !important;
5
+ }
6
+ }
@@ -97,71 +97,104 @@ var InternalUpload = function InternalUpload(props, ref) {
97
97
  void messageApi.info('请上传5M以内的图片');
98
98
  return false;
99
99
  }
100
+ // 校验图片尺寸
101
+ var reader = new FileReader();
102
+ reader.readAsDataURL(file);
103
+ reader.onload = function (e) {
104
+ var _e$target;
105
+ var image = new Image();
106
+ image.src = (_e$target = e.target) === null || _e$target === void 0 ? void 0 : _e$target.result;
107
+ // 上传图片
108
+ image.onload = function () {
109
+ if (widthPixels != null && heightPixels != null) {
110
+ if (image.width !== widthPixels || image.height !== heightPixels) {
111
+ void messageApi.warning("\u8BF7\u4E0A\u4F20\u5C3A\u5BF8\u4E3A".concat(widthPixels, "*").concat(heightPixels, "\u7684\u56FE\u7247"));
112
+ return;
113
+ }
114
+ } else if (widthPixels != null && heightPixels == null) {
115
+ if (image.width !== widthPixels) {
116
+ void messageApi.warning("\u8BF7\u4E0A\u4F20\u5BBD\u5EA6\u4E3A".concat(widthPixels, "\u7684\u56FE\u7247"));
117
+ return;
118
+ }
119
+ } else if (widthPixels == null && heightPixels != null) {
120
+ if (image.height !== heightPixels) {
121
+ void messageApi.warning("\u8BF7\u4E0A\u4F20\u9AD8\u5EA6\u4E3A".concat(heightPixels, "\u7684\u56FE\u7247"));
122
+ return;
123
+ }
124
+ }
125
+ // 图片尺寸符合要求,上传图片
126
+ var formData = new FormData();
127
+ if (folder != null) {
128
+ formData.append('folder', folder);
129
+ }
130
+ formData.append('files', file);
131
+ formData.append('user_origin_name', 'true');
132
+ void request({
133
+ url: "/v1/file/multi-upload1",
134
+ method: 'post',
135
+ data: formData,
136
+ headers: {
137
+ 'Content-Type': 'multipart/form-data'
138
+ }
139
+ }).then(function (res) {
140
+ var _fileList = Array.from([]);
141
+ // eslint-disable-next-line @typescript-eslint/ban-ts-comment
142
+ // @ts-expect-error
143
+ res === null || res === void 0 || res.forEach(function (item) {
144
+ _fileList.push({
145
+ name: file.name,
146
+ url: item.filename,
147
+ uid: file.uid,
148
+ preview: item.filename,
149
+ status: 'done'
150
+ });
151
+ });
152
+ onChange === null || onChange === void 0 || onChange([].concat(_toConsumableArray(fileList), _fileList));
153
+ // setFileList([...fileList, ..._fileList]);
154
+ }).catch(function () {
155
+ var msg = '上传失败!';
156
+ void messageApi.error(msg);
157
+ });
158
+ };
159
+ };
100
160
  } else if (/\.(mp4)$/i.test(file.name)) {
101
161
  if ((file === null || file === void 0 ? void 0 : file.size) / 1024 / 1024 > 200) {
102
162
  void messageApi.info('请上传200M以内的视频');
103
163
  return false;
104
164
  }
105
- }
106
- // 校验图片尺寸
107
- var reader = new FileReader();
108
- reader.readAsDataURL(file);
109
- reader.onload = function (e) {
110
- var _e$target;
111
- var image = new Image();
112
- image.src = (_e$target = e.target) === null || _e$target === void 0 ? void 0 : _e$target.result;
113
- image.onload = function () {
114
- if (widthPixels != null && heightPixels != null) {
115
- if (image.width !== widthPixels || image.height !== heightPixels) {
116
- void messageApi.warning("\u8BF7\u4E0A\u4F20\u5C3A\u5BF8\u4E3A".concat(widthPixels, "*").concat(heightPixels, "\u7684\u56FE\u7247"));
117
- return;
118
- }
119
- } else if (widthPixels != null && heightPixels == null) {
120
- if (image.width !== widthPixels) {
121
- void messageApi.warning("\u8BF7\u4E0A\u4F20\u5BBD\u5EA6\u4E3A".concat(widthPixels, "\u7684\u56FE\u7247"));
122
- return;
123
- }
124
- } else if (widthPixels == null && heightPixels != null) {
125
- if (image.height !== heightPixels) {
126
- void messageApi.warning("\u8BF7\u4E0A\u4F20\u9AD8\u5EA6\u4E3A".concat(heightPixels, "\u7684\u56FE\u7247"));
127
- return;
128
- }
129
- }
130
- // 图片尺寸符合要求,上传图片
131
- var formData = new FormData();
132
- if (folder != null) {
133
- formData.append('folder', folder);
165
+ var formData = new FormData();
166
+ if (folder != null) {
167
+ formData.append('folder', folder);
168
+ }
169
+ formData.append('files', file);
170
+ formData.append('user_origin_name', 'true');
171
+ void request({
172
+ url: "/v1/file/multi-upload1",
173
+ method: 'post',
174
+ data: formData,
175
+ headers: {
176
+ 'Content-Type': 'multipart/form-data'
134
177
  }
135
- formData.append('files', file);
136
- formData.append('user_origin_name', 'true');
137
- void request({
138
- url: "/v1/file/multi-upload1",
139
- method: 'post',
140
- data: formData,
141
- headers: {
142
- 'Content-Type': 'multipart/form-data'
143
- }
144
- }).then(function (res) {
145
- var _fileList = Array.from([]);
146
- // eslint-disable-next-line @typescript-eslint/ban-ts-comment
147
- // @ts-expect-error
148
- res === null || res === void 0 || res.forEach(function (item) {
149
- _fileList.push({
150
- name: file.name,
151
- url: item.filename,
152
- uid: file.uid,
153
- preview: item.filename,
154
- status: 'done'
155
- });
178
+ }).then(function (res) {
179
+ var _fileList = Array.from([]);
180
+ // eslint-disable-next-line @typescript-eslint/ban-ts-comment
181
+ // @ts-expect-error
182
+ res === null || res === void 0 || res.forEach(function (item) {
183
+ _fileList.push({
184
+ name: file.name,
185
+ url: item.filename,
186
+ uid: file.uid,
187
+ preview: item.filename,
188
+ status: 'done'
156
189
  });
157
- onChange === null || onChange === void 0 || onChange([].concat(_toConsumableArray(fileList), _fileList));
158
- // setFileList([...fileList, ..._fileList]);
159
- }).catch(function () {
160
- var msg = '上传失败!';
161
- void messageApi.error(msg);
162
190
  });
163
- };
164
- };
191
+ onChange === null || onChange === void 0 || onChange([].concat(_toConsumableArray(fileList), _fileList));
192
+ // setFileList([...fileList, ..._fileList]);
193
+ }).catch(function () {
194
+ var msg = '上传失败!';
195
+ void messageApi.error(msg);
196
+ });
197
+ }
165
198
  return false;
166
199
  }
167
200
  var onRemove = function onRemove(file) {
@@ -15,11 +15,14 @@ function _arrayLikeToArray(arr, len) { if (len == null || len > arr.length) len
15
15
  function _iterableToArrayLimit(r, l) { var t = null == r ? null : "undefined" != typeof Symbol && r[Symbol.iterator] || r["@@iterator"]; if (null != t) { var e, n, i, u, a = [], f = !0, o = !1; try { if (i = (t = t.call(r)).next, 0 === l) { if (Object(t) !== t) return; f = !1; } else for (; !(f = (e = i.call(t)).done) && (a.push(e.value), a.length !== l); f = !0); } catch (r) { o = !0, n = r; } finally { try { if (!f && null != t.return && (u = t.return(), Object(u) !== u)) return; } finally { if (o) throw n; } } return a; } }
16
16
  function _arrayWithHoles(arr) { if (Array.isArray(arr)) return arr; }
17
17
  import * as faceapi from '@vladmandic/face-api';
18
+ import * as posedetection from '@tensorflow-models/pose-detection';
19
+ import * as tf from '@tensorflow/tfjs';
18
20
  import React, { forwardRef, useCallback, useEffect, useImperativeHandle, useRef, useState } from 'react';
19
21
  import { EndPoint } from 'yootd-webrtc-sdk';
20
22
  import { useBem } from "../hooks/useBem";
21
23
  import "./index.scss";
22
24
  import { throttle } from 'lodash';
25
+ import { message } from "./..";
23
26
  import { useOSS } from "../hooks/useOSS";
24
27
  import controlBottomBg from "./assets/control-background.png";
25
28
  var PROGRESS_BAR_HEIGHT = 63;
@@ -52,89 +55,95 @@ export var VideoPlayer = /*#__PURE__*/forwardRef(function (_ref, ref) {
52
55
  var containerRef = useRef(null);
53
56
  var videoRef = useRef(null);
54
57
  var canvasRef = useRef(null);
58
+ var poseCanvasRef = useRef(null);
59
+ var _useState = useState(null),
60
+ _useState2 = _slicedToArray(_useState, 2),
61
+ poseDetector = _useState2[0],
62
+ setPoseDetector = _useState2[1];
55
63
  var OSS = useOSS();
56
64
  var bem = useBem('video-player');
57
- var _useState = useState(true),
58
- _useState2 = _slicedToArray(_useState, 1),
59
- show = _useState2[0];
60
- var _useState3 = useState(false),
61
- _useState4 = _slicedToArray(_useState3, 2),
62
- isFullScreen = _useState4[0],
63
- setIsFullScreen = _useState4[1];
65
+ var _useState3 = useState(true),
66
+ _useState4 = _slicedToArray(_useState3, 1),
67
+ show = _useState4[0];
64
68
  var _useState5 = useState(false),
65
69
  _useState6 = _slicedToArray(_useState5, 2),
66
- isPlaying = _useState6[0],
67
- setIsPlaying = _useState6[1];
68
- var _useState7 = useState(0),
70
+ isFullScreen = _useState6[0],
71
+ setIsFullScreen = _useState6[1];
72
+ var _useState7 = useState(false),
69
73
  _useState8 = _slicedToArray(_useState7, 2),
70
- volume = _useState8[0],
71
- setVolume = _useState8[1];
72
- var _useState9 = useState(false),
74
+ isPlaying = _useState8[0],
75
+ setIsPlaying = _useState8[1];
76
+ var _useState9 = useState(0),
73
77
  _useState10 = _slicedToArray(_useState9, 2),
74
- hasAudio = _useState10[0],
75
- setHasAudio = _useState10[1];
76
- var _useState11 = useState(0),
78
+ volume = _useState10[0],
79
+ setVolume = _useState10[1];
80
+ var _useState11 = useState(false),
77
81
  _useState12 = _slicedToArray(_useState11, 2),
78
- currentTime = _useState12[0],
79
- setCurrentTime = _useState12[1];
80
- var _useState13 = useState(Number.MAX_SAFE_INTEGER),
82
+ hasAudio = _useState12[0],
83
+ setHasAudio = _useState12[1];
84
+ var _useState13 = useState(0),
81
85
  _useState14 = _slicedToArray(_useState13, 2),
82
- duration = _useState14[0],
83
- setDuration = _useState14[1];
84
- var _useState15 = useState(false),
86
+ currentTime = _useState14[0],
87
+ setCurrentTime = _useState14[1];
88
+ var _useState15 = useState(Number.MAX_SAFE_INTEGER),
85
89
  _useState16 = _slicedToArray(_useState15, 2),
86
- showSpeedPicker = _useState16[0],
87
- setShowSpeedPicker = _useState16[1];
88
- var _useState17 = useState('1.0'),
90
+ duration = _useState16[0],
91
+ setDuration = _useState16[1];
92
+ var _useState17 = useState(false),
89
93
  _useState18 = _slicedToArray(_useState17, 2),
90
- speed = _useState18[0],
91
- setSpeed = _useState18[1];
92
- var _useState19 = useState(false),
94
+ showSpeedPicker = _useState18[0],
95
+ setShowSpeedPicker = _useState18[1];
96
+ var _useState19 = useState('1.0'),
93
97
  _useState20 = _slicedToArray(_useState19, 2),
94
- showVolumeSlider = _useState20[0],
95
- setShowVolumeSlider = _useState20[1];
98
+ speed = _useState20[0],
99
+ setSpeed = _useState20[1];
96
100
  var _useState21 = useState(false),
97
101
  _useState22 = _slicedToArray(_useState21, 2),
98
- mouseDown = _useState22[0],
99
- setMouseDown = _useState22[1];
100
- var _useState23 = useState(0),
102
+ showVolumeSlider = _useState22[0],
103
+ setShowVolumeSlider = _useState22[1];
104
+ var _useState23 = useState(false),
101
105
  _useState24 = _slicedToArray(_useState23, 2),
102
- buffered = _useState24[0],
103
- setBuffered = _useState24[1];
104
- var _useState25 = useState(false),
106
+ mouseDown = _useState24[0],
107
+ setMouseDown = _useState24[1];
108
+ var _useState25 = useState(0),
105
109
  _useState26 = _slicedToArray(_useState25, 2),
106
- showSettingPanel = _useState26[0],
107
- setShowSettingPanel = _useState26[1];
108
- var _useState27 = useState({
110
+ buffered = _useState26[0],
111
+ setBuffered = _useState26[1];
112
+ var _useState27 = useState(false),
113
+ _useState28 = _slicedToArray(_useState27, 2),
114
+ showSettingPanel = _useState28[0],
115
+ setShowSettingPanel = _useState28[1];
116
+ var _useState29 = useState({
109
117
  emotion: false,
110
118
  character: false,
111
- anchor: false
119
+ anchor: false,
120
+ pose: false
112
121
  }),
113
- _useState28 = _slicedToArray(_useState27, 2),
114
- faceFeature = _useState28[0],
115
- setFaceFeature = _useState28[1];
116
- var _useState29 = useState(null),
117
122
  _useState30 = _slicedToArray(_useState29, 2),
118
- options = _useState30[0],
119
- setOptions = _useState30[1];
120
- var _useState31 = useState(false),
123
+ aiFeature = _useState30[0],
124
+ setAIFeature = _useState30[1];
125
+ var _useState31 = useState(null),
121
126
  _useState32 = _slicedToArray(_useState31, 2),
122
- faceApiInited = _useState32[0],
123
- setFaceApiInited = _useState32[1];
124
- var _useState33 = useState({
125
- width: 0,
126
- height: 0
127
- }),
127
+ options = _useState32[0],
128
+ setOptions = _useState32[1];
129
+ var _useState33 = useState(false),
128
130
  _useState34 = _slicedToArray(_useState33, 2),
129
- canvasSize = _useState34[0],
130
- setCanvasSize = _useState34[1];
131
+ faceApiInited = _useState34[0],
132
+ setFaceApiInited = _useState34[1];
131
133
  var _useState35 = useState({
132
134
  width: 0,
133
135
  height: 0
134
136
  }),
135
137
  _useState36 = _slicedToArray(_useState35, 2),
136
- videoEleSize = _useState36[0],
137
- setVideoEleSize = _useState36[1];
138
+ canvasSize = _useState36[0],
139
+ setCanvasSize = _useState36[1];
140
+ var _useState37 = useState({
141
+ width: 0,
142
+ height: 0
143
+ }),
144
+ _useState38 = _slicedToArray(_useState37, 2),
145
+ videoEleSize = _useState38[0],
146
+ setVideoEleSize = _useState38[1];
138
147
  useImperativeHandle(ref, function () {
139
148
  return {
140
149
  play: function play() {
@@ -257,7 +266,6 @@ export var VideoPlayer = /*#__PURE__*/forwardRef(function (_ref, ref) {
257
266
  }
258
267
  };
259
268
  var handleHideVolumeSlider = function handleHideVolumeSlider() {
260
- console.log('hide');
261
269
  setShowVolumeSlider(false);
262
270
  setMouseDown(false);
263
271
  };
@@ -304,22 +312,22 @@ export var VideoPlayer = /*#__PURE__*/forwardRef(function (_ref, ref) {
304
312
  case 0:
305
313
  _context.prev = 0;
306
314
  _context.next = 3;
307
- return faceapi.nets.ssdMobilenetv1.load("".concat(OSS, "/face-api-models/model"));
315
+ return faceapi.nets.ssdMobilenetv1.load("".concat(OSS, "/model-zoo/face-api-models/model"));
308
316
  case 3:
309
317
  _context.next = 5;
310
- return faceapi.nets.ssdMobilenetv1.load("".concat(OSS, "/face-api-models/model"));
318
+ return faceapi.nets.ssdMobilenetv1.load("".concat(OSS, "/model-zoo/face-api-models/model"));
311
319
  case 5:
312
320
  _context.next = 7;
313
321
  return faceapi.nets.ageGenderNet.load("".concat(OSS, "/face-api-models/model"));
314
322
  case 7:
315
323
  _context.next = 9;
316
- return faceapi.nets.faceLandmark68Net.load("".concat(OSS, "/face-api-models/model"));
324
+ return faceapi.nets.faceLandmark68Net.load("".concat(OSS, "/model-zoo/face-api-models/model"));
317
325
  case 9:
318
326
  _context.next = 11;
319
- return faceapi.nets.faceRecognitionNet.load("".concat(OSS, "/face-api-models/model"));
327
+ return faceapi.nets.faceRecognitionNet.load("".concat(OSS, "/model-zoo/face-api-models/model"));
320
328
  case 11:
321
329
  _context.next = 13;
322
- return faceapi.nets.faceExpressionNet.load("".concat(OSS, "/face-api-models/model"));
330
+ return faceapi.nets.faceExpressionNet.load("".concat(OSS, "/model-zoo/face-api-models/model"));
323
331
  case 13:
324
332
  setOptions(new faceapi.SsdMobilenetv1Options({
325
333
  minConfidence: MIN_SCORE,
@@ -339,6 +347,38 @@ export var VideoPlayer = /*#__PURE__*/forwardRef(function (_ref, ref) {
339
347
  }, _callee, null, [[0, 17]]);
340
348
  }))();
341
349
  }, []);
350
+ var initPoseDetecter = useCallback(function () {
351
+ _asyncToGenerator( /*#__PURE__*/_regeneratorRuntime().mark(function _callee2() {
352
+ var detectorConfig, _poseDetector;
353
+ return _regeneratorRuntime().wrap(function _callee2$(_context2) {
354
+ while (1) switch (_context2.prev = _context2.next) {
355
+ case 0:
356
+ _context2.prev = 0;
357
+ detectorConfig = {
358
+ modelType: posedetection.movenet.modelType.MULTIPOSE_LIGHTNING,
359
+ enableTracking: true,
360
+ trackerType: posedetection.TrackerType.BoundingBox,
361
+ scoreThreshold: 0.3,
362
+ modelUrl: "".concat(OSS, "/model-zoo/pose-detection-models/model.json")
363
+ };
364
+ _context2.next = 4;
365
+ return posedetection.createDetector(posedetection.SupportedModels.MoveNet, detectorConfig);
366
+ case 4:
367
+ _poseDetector = _context2.sent;
368
+ setPoseDetector(_poseDetector);
369
+ _context2.next = 11;
370
+ break;
371
+ case 8:
372
+ _context2.prev = 8;
373
+ _context2.t0 = _context2["catch"](0);
374
+ void message.error('初始化姿态检测器失败');
375
+ case 11:
376
+ case "end":
377
+ return _context2.stop();
378
+ }
379
+ }, _callee2, null, [[0, 8]]);
380
+ }))();
381
+ }, []);
342
382
  var drawFaces = useCallback(function (canvas, detections, fps, faceFeature) {
343
383
  var ctx = canvas.getContext('2d', {
344
384
  willReadFrequently: true
@@ -449,7 +489,7 @@ export var VideoPlayer = /*#__PURE__*/forwardRef(function (_ref, ref) {
449
489
  _iterator.f();
450
490
  }
451
491
  }, []);
452
- var detect = useCallback(function () {
492
+ var detectFaces = useCallback(function () {
453
493
  return new Promise(function (resolve, reject) {
454
494
  if (videoRef.current != null && options != null && faceApiInited) {
455
495
  var t0 = performance.now();
@@ -459,7 +499,7 @@ export var VideoPlayer = /*#__PURE__*/forwardRef(function (_ref, ref) {
459
499
  .then(function (detections) {
460
500
  if (canvasRef.current != null) {
461
501
  var fps = 1000 / (performance.now() - t0);
462
- drawFaces(canvasRef.current, detections, fps.toLocaleString(), faceFeature);
502
+ drawFaces(canvasRef.current, detections, fps.toLocaleString(), aiFeature);
463
503
  resolve(true);
464
504
  } else {
465
505
  reject(false);
@@ -469,7 +509,93 @@ export var VideoPlayer = /*#__PURE__*/forwardRef(function (_ref, ref) {
469
509
  });
470
510
  }
471
511
  });
472
- }, [drawFaces, faceApiInited, faceFeature, options]);
512
+
513
+ // 肢体检测
514
+ }, [drawFaces, faceApiInited, aiFeature, options]);
515
+ var drawKeyPoints = function drawKeyPoints(keypoints, ctx) {
516
+ keypoints.forEach(function (keypoint) {
517
+ if (keypoint.score && keypoint.score > 0.3) {
518
+ ctx.beginPath();
519
+ ctx.arc(keypoint.x, keypoint.y, 5, 0, 2 * Math.PI);
520
+ ctx.fillStyle = 'red';
521
+ ctx.fill();
522
+
523
+ // 添加关键点标签,帮助调试
524
+ ctx.fillStyle = 'white';
525
+ ctx.fillText("".concat(Math.round(keypoint.score * 100), "%"), keypoint.x + 5, keypoint.y - 5);
526
+ }
527
+ });
528
+ };
529
+
530
+ // 绘制骨架
531
+ var drawSkeleton = function drawSkeleton(keypoints, ctx) {
532
+ var adjacentPairs = posedetection.util.getAdjacentPairs(posedetection.SupportedModels.MoveNet);
533
+ adjacentPairs.forEach(function (_ref4) {
534
+ var _ref5 = _slicedToArray(_ref4, 2),
535
+ i = _ref5[0],
536
+ j = _ref5[1];
537
+ var kp1 = keypoints[i];
538
+ var kp2 = keypoints[j];
539
+ if (kp1.score && kp2.score && kp1.score > 0.3 && kp2.score > 0.3) {
540
+ ctx.beginPath();
541
+ ctx.moveTo(kp1.x, kp1.y);
542
+ ctx.lineTo(kp2.x, kp2.y);
543
+ ctx.strokeStyle = 'blue';
544
+ ctx.lineWidth = 2;
545
+ ctx.stroke();
546
+ }
547
+ });
548
+ };
549
+ var drawPose = useCallback(function (canvas, pose) {
550
+ var ctx = canvas.getContext('2d');
551
+ if (ctx == null) {
552
+ return;
553
+ }
554
+ ctx.clearRect(0, 0, canvas.width, canvas.height);
555
+ pose.forEach(function (p) {
556
+ drawKeyPoints(p.keypoints, ctx);
557
+ drawSkeleton(p.keypoints, ctx);
558
+ });
559
+ }, []);
560
+ var detectPose = useCallback(function () {
561
+ if (poseDetector == null || videoRef.current == null || poseCanvasRef.current == null) {
562
+ return;
563
+ }
564
+ var video = videoRef.current;
565
+ var canvas = poseCanvasRef.current;
566
+ var detect = /*#__PURE__*/function () {
567
+ var _ref6 = _asyncToGenerator( /*#__PURE__*/_regeneratorRuntime().mark(function _callee3() {
568
+ var pose;
569
+ return _regeneratorRuntime().wrap(function _callee3$(_context3) {
570
+ while (1) switch (_context3.prev = _context3.next) {
571
+ case 0:
572
+ _context3.prev = 0;
573
+ _context3.next = 3;
574
+ return poseDetector.estimatePoses(video, {
575
+ flipHorizontal: false,
576
+ maxPoses: 1
577
+ });
578
+ case 3:
579
+ pose = _context3.sent;
580
+ drawPose(canvas, pose);
581
+ _context3.next = 10;
582
+ break;
583
+ case 7:
584
+ _context3.prev = 7;
585
+ _context3.t0 = _context3["catch"](0);
586
+ console.error('检测肢体失败', _context3.t0);
587
+ case 10:
588
+ case "end":
589
+ return _context3.stop();
590
+ }
591
+ }, _callee3, null, [[0, 7]]);
592
+ }));
593
+ return function detect() {
594
+ return _ref6.apply(this, arguments);
595
+ };
596
+ }();
597
+ detect();
598
+ }, [poseDetector]);
473
599
  var handleCapture = function handleCapture() {
474
600
  if (videoRef.current != null) {
475
601
  var _canvas$getContext;
@@ -528,11 +654,33 @@ export var VideoPlayer = /*#__PURE__*/forwardRef(function (_ref, ref) {
528
654
  };
529
655
  }, []);
530
656
  useEffect(function () {
531
- if ((faceFeature.emotion || faceFeature.character || faceFeature.anchor) && !faceApiInited) {
532
- // 开始初始化人脸
533
- initFaceApi();
534
- }
535
- }, [faceFeature, faceApiInited, initFaceApi]);
657
+ _asyncToGenerator( /*#__PURE__*/_regeneratorRuntime().mark(function _callee4() {
658
+ return _regeneratorRuntime().wrap(function _callee4$(_context4) {
659
+ while (1) switch (_context4.prev = _context4.next) {
660
+ case 0:
661
+ _context4.prev = 0;
662
+ _context4.next = 3;
663
+ return tf.ready();
664
+ case 3:
665
+ if ((aiFeature.emotion || aiFeature.character || aiFeature.anchor) && !faceApiInited) {
666
+ // 开始初始化人脸
667
+ initFaceApi();
668
+ }
669
+ if (aiFeature.pose && !poseDetector) {
670
+ initPoseDetecter();
671
+ }
672
+ _context4.next = 9;
673
+ break;
674
+ case 7:
675
+ _context4.prev = 7;
676
+ _context4.t0 = _context4["catch"](0);
677
+ case 9:
678
+ case "end":
679
+ return _context4.stop();
680
+ }
681
+ }, _callee4, null, [[0, 7]]);
682
+ }))();
683
+ }, [aiFeature, faceApiInited, initFaceApi, initPoseDetecter, poseDetector]);
536
684
  useEffect(function () {
537
685
  var handler = null;
538
686
  // let lastTime = Date.now();
@@ -558,23 +706,31 @@ export var VideoPlayer = /*#__PURE__*/forwardRef(function (_ref, ref) {
558
706
  }
559
707
  }; */
560
708
 
561
- var start = function start() {
562
- if (!faceFeature.anchor && !faceFeature.emotion && !faceFeature.character) {
709
+ var lastTime = 0;
710
+ var fps = 30;
711
+ var start = function start(currentTime) {
712
+ if (currentTime - lastTime < 1000 / fps) {
713
+ handler = requestAnimationFrame(start);
563
714
  return;
564
715
  }
565
- detect().catch(function (e) {
566
- console.log('error', e);
567
- }).finally(function () {
568
- handler = requestAnimationFrame(start);
569
- });
716
+ lastTime = currentTime;
717
+ if (aiFeature.anchor || aiFeature.emotion || aiFeature.character) {
718
+ detectFaces().catch(function (e) {
719
+ console.log('error', e);
720
+ }).finally(function () {});
721
+ }
722
+ if (aiFeature.pose) {
723
+ detectPose();
724
+ }
725
+ handler = requestAnimationFrame(start);
570
726
  };
571
- start();
727
+ start(0);
572
728
  return function () {
573
729
  if (handler != null) {
574
730
  cancelAnimationFrame(handler);
575
731
  }
576
732
  };
577
- }, [detect, faceFeature.anchor, faceFeature.character, faceFeature.emotion]);
733
+ }, [detectFaces, detectPose, aiFeature.anchor, aiFeature.character, aiFeature.emotion, aiFeature.pose]);
578
734
  useEffect(function () {
579
735
  var handleClick = function handleClick() {
580
736
  setShowSettingPanel(false);
@@ -801,9 +957,9 @@ export var VideoPlayer = /*#__PURE__*/forwardRef(function (_ref, ref) {
801
957
  },
802
958
  type: 'checkbox',
803
959
  className: "".concat(bem.b('container').e('controls-setting').e('panel').e('item').e('checkbox')),
804
- checked: faceFeature.emotion,
960
+ checked: aiFeature.emotion,
805
961
  onChange: function onChange(e) {
806
- setFaceFeature(function (prev) {
962
+ setAIFeature(function (prev) {
807
963
  return _objectSpread(_objectSpread({}, prev), {}, {
808
964
  emotion: e.target.checked
809
965
  });
@@ -817,9 +973,9 @@ export var VideoPlayer = /*#__PURE__*/forwardRef(function (_ref, ref) {
817
973
  },
818
974
  type: 'checkbox',
819
975
  className: "".concat(bem.b('container').e('controls-setting').e('panel').e('item').e('checkbox')),
820
- checked: faceFeature.character,
976
+ checked: aiFeature.character,
821
977
  onChange: function onChange(e) {
822
- setFaceFeature(function (prev) {
978
+ setAIFeature(function (prev) {
823
979
  return _objectSpread(_objectSpread({}, prev), {}, {
824
980
  character: e.target.checked
825
981
  });
@@ -833,14 +989,30 @@ export var VideoPlayer = /*#__PURE__*/forwardRef(function (_ref, ref) {
833
989
  },
834
990
  type: 'checkbox',
835
991
  className: "".concat(bem.b('container').e('controls-setting').e('panel').e('item').e('checkbox')),
836
- checked: faceFeature.anchor,
992
+ checked: aiFeature.anchor,
837
993
  onChange: function onChange(e) {
838
- setFaceFeature(function (prev) {
994
+ setAIFeature(function (prev) {
839
995
  return _objectSpread(_objectSpread({}, prev), {}, {
840
996
  anchor: e.target.checked
841
997
  });
842
998
  });
843
999
  }
1000
+ })), /*#__PURE__*/React.createElement("div", {
1001
+ className: "".concat(bem.b('container').e('controls-setting').e('panel').e('item'))
1002
+ }, /*#__PURE__*/React.createElement("div", null, "\u80A2\u4F53\u7EBF\u6761"), /*#__PURE__*/React.createElement("input", {
1003
+ onClick: function onClick(e) {
1004
+ return e.stopPropagation();
1005
+ },
1006
+ type: 'checkbox',
1007
+ className: "".concat(bem.b('container').e('controls-setting').e('panel').e('item').e('checkbox')),
1008
+ checked: aiFeature.pose,
1009
+ onChange: function onChange(e) {
1010
+ setAIFeature(function (prev) {
1011
+ return _objectSpread(_objectSpread({}, prev), {}, {
1012
+ pose: e.target.checked
1013
+ });
1014
+ });
1015
+ }
844
1016
  }))) : null), !isFullScreen ? /*#__PURE__*/React.createElement("svg", {
845
1017
  className: "".concat(bem.b('container').e('controls-full-screen')),
846
1018
  onClick: handleFullScreen,
@@ -877,7 +1049,7 @@ export var VideoPlayer = /*#__PURE__*/forwardRef(function (_ref, ref) {
877
1049
  style: {
878
1050
  width: "".concat(currentTime / duration * 100, "%")
879
1051
  }
880
- }))), faceFeature.anchor || faceFeature.emotion || faceFeature.character ? /*#__PURE__*/React.createElement("canvas", {
1052
+ }))), aiFeature.anchor || aiFeature.emotion || aiFeature.character ? /*#__PURE__*/React.createElement("canvas", {
881
1053
  className: "".concat(bem.b('container').e('canvas')),
882
1054
  width: videoEleSize.width,
883
1055
  height: videoEleSize.height,
@@ -885,6 +1057,14 @@ export var VideoPlayer = /*#__PURE__*/forwardRef(function (_ref, ref) {
885
1057
  style: {
886
1058
  transform: "scale(".concat(canvasSize.width / videoEleSize.width, ")")
887
1059
  }
1060
+ }) : null, aiFeature.pose ? /*#__PURE__*/React.createElement("canvas", {
1061
+ className: "".concat(bem.b('container').e('canvas')),
1062
+ width: videoEleSize.width,
1063
+ height: videoEleSize.height,
1064
+ ref: poseCanvasRef,
1065
+ style: {
1066
+ transform: "scale(".concat(canvasSize.width / videoEleSize.width, ")")
1067
+ }
888
1068
  }) : null));
889
1069
  });
890
1070
  VideoPlayer.displayName = 'VideoPlayer';
@@ -237,7 +237,7 @@
237
237
  width: 96px;
238
238
  left: 50%;
239
239
  margin-left: -48px;
240
- margin-bottom: 24px;
240
+ margin-bottom: 40px;
241
241
  bottom: 0;
242
242
  position: absolute;
243
243
  font-size: 12px;
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "yootd",
3
- "version": "0.0.63",
3
+ "version": "0.0.65",
4
4
  "description": "A react library developed with dumi",
5
5
  "license": "MIT",
6
6
  "module": "dist/index.js",
@@ -44,6 +44,10 @@
44
44
  "prettier --parser=typescript --write"
45
45
  ]
46
46
  },
47
+ "dependencies": {
48
+ "@tensorflow-models/pose-detection": "^2.1.3",
49
+ "@tensorflow/tfjs": "^4.22.0"
50
+ },
47
51
  "devDependencies": {
48
52
  "@commitlint/cli": "^17.1.2",
49
53
  "@commitlint/config-conventional": "^17.1.0",