diff --git a/modelscope/models/multi_modal/mmr/models/clip_for_mm_video_embedding.py b/modelscope/models/multi_modal/mmr/models/clip_for_mm_video_embedding.py index 657f52f8..88a4ddda 100644 --- a/modelscope/models/multi_modal/mmr/models/clip_for_mm_video_embedding.py +++ b/modelscope/models/multi_modal/mmr/models/clip_for_mm_video_embedding.py @@ -5,6 +5,7 @@ from typing import Any, Dict import json import numpy as np import torch +from decord import VideoReader, cpu from PIL import Image from modelscope.metainfo import Models @@ -131,7 +132,6 @@ class VideoCLIPForMultiModalEmbedding(TorchModel): end_time = end_time + 1 if exists(video_path): - from decord import VideoReader, cpu vreader = VideoReader(video_path, ctx=cpu(0)) else: logger.error('non video input, output is wrong!!!') diff --git a/modelscope/pipelines/cv/cmdssl_video_embedding_pipeline.py b/modelscope/pipelines/cv/cmdssl_video_embedding_pipeline.py index f29d766c..9f4e2d93 100644 --- a/modelscope/pipelines/cv/cmdssl_video_embedding_pipeline.py +++ b/modelscope/pipelines/cv/cmdssl_video_embedding_pipeline.py @@ -1,6 +1,7 @@ import os.path as osp from typing import Any, Dict +import decord import numpy as np import torch import torchvision.transforms.functional as TF @@ -45,7 +46,6 @@ class CMDSSLVideoEmbeddingPipeline(Pipeline): logger.info('load model done') def preprocess(self, input: Input) -> Dict[str, Any]: - import decord decord.bridge.set_bridge('native') transforms = VCompose([ diff --git a/modelscope/pipelines/cv/live_category_pipeline.py b/modelscope/pipelines/cv/live_category_pipeline.py index 348908d3..b7f3202e 100644 --- a/modelscope/pipelines/cv/live_category_pipeline.py +++ b/modelscope/pipelines/cv/live_category_pipeline.py @@ -2,12 +2,14 @@ import os.path as osp from typing import Any, Dict +import decord import numpy as np import torch import torch.nn as nn import torch.nn.functional as F import torchvision.models as models import torchvision.transforms.functional as TF +from decord import VideoReader, cpu from PIL import Image from modelscope.metainfo import Pipelines @@ -56,8 +58,6 @@ class LiveCategoryPipeline(Pipeline): def preprocess(self, input: Input) -> Dict[str, Any]: if isinstance(input, str): - import decord - from decord import VideoReader, cpu decord.bridge.set_bridge('native') vr = VideoReader(input, ctx=cpu(0)) indices = np.linspace(0, len(vr) - 1, 4).astype(int) diff --git a/modelscope/pipelines/cv/video_category_pipeline.py b/modelscope/pipelines/cv/video_category_pipeline.py index 2d38031a..196d3115 100644 --- a/modelscope/pipelines/cv/video_category_pipeline.py +++ b/modelscope/pipelines/cv/video_category_pipeline.py @@ -2,6 +2,7 @@ import os.path as osp from typing import Any, Dict +import decord import json import numpy as np import torch @@ -9,6 +10,7 @@ import torch.nn as nn import torch.nn.functional as F import torchvision.models as models import torchvision.transforms.functional as TF +from decord import VideoReader, cpu from PIL import Image from modelscope.metainfo import Pipelines @@ -67,8 +69,6 @@ class VideoCategoryPipeline(Pipeline): def preprocess(self, input: Input) -> Dict[str, Any]: if isinstance(input, str): - import decord - from decord import VideoReader, cpu decord.bridge.set_bridge('native') vr = VideoReader(input, ctx=cpu(0)) indices = np.linspace(0, len(vr) - 1, 16).astype(int) diff --git a/modelscope/preprocessors/video.py b/modelscope/preprocessors/video.py index 33a92c1c..36110d1b 100644 --- a/modelscope/preprocessors/video.py +++ b/modelscope/preprocessors/video.py @@ -6,6 +6,7 @@ import torch import torch.utils.data import torch.utils.dlpack as dlpack import torchvision.transforms._transforms_video as transforms +from decord import VideoReader from torchvision.transforms import Compose @@ -124,7 +125,6 @@ def _decode_video(cfg, path): Returns: frames (Tensor): video tensor data """ - from decord import VideoReader vr = VideoReader(path) num_clips_per_video = cfg.TEST.NUM_ENSEMBLE_VIEWS diff --git a/modelscope/utils/error.py b/modelscope/utils/error.py index 82c771a2..e7d1442f 100644 --- a/modelscope/utils/error.py +++ b/modelscope/utils/error.py @@ -91,3 +91,8 @@ GENERAL_IMPORT_ERROR = """ {0} requires the REQ library but it was not found in your environment. You can install it with pip: `pip install REQ` """ + +DECORD_IMPORT_ERROR = """ +{0} requires the decord library but it was not found in your environment. You can install it with pip: +`pip install decord>=0.6.0` +""" diff --git a/modelscope/utils/import_utils.py b/modelscope/utils/import_utils.py index 82f4e0ef..85f442a7 100644 --- a/modelscope/utils/import_utils.py +++ b/modelscope/utils/import_utils.py @@ -287,7 +287,8 @@ REQUIREMENTS_MAAPING = OrderedDict([ ('espnet', (is_espnet_available, GENERAL_IMPORT_ERROR.replace('REQ', 'espnet'))), ('easyasr', (is_package_available('easyasr'), AUDIO_IMPORT_ERROR)), - ('kwsbp', (is_package_available('kwsbp'), AUDIO_IMPORT_ERROR)) + ('kwsbp', (is_package_available('kwsbp'), AUDIO_IMPORT_ERROR)), + ('decord', (is_package_available('decord'), DECORD_IMPORT_ERROR)), ]) SYSTEM_PACKAGE = set(['os', 'sys', 'typing']) @@ -308,7 +309,7 @@ def requires(obj, requirements): if req in REQUIREMENTS_MAAPING: check = REQUIREMENTS_MAAPING[req] else: - check_fn = functools.partial(is_package_available, req) + check_fn = is_package_available(req) err_msg = GENERAL_IMPORT_ERROR.replace('REQ', req) check = (check_fn, err_msg) checks.append(check) @@ -433,6 +434,10 @@ class LazyImportModule(ModuleType): if signature in LazyImportModule.AST_INDEX[INDEX_KEY]: mod_index = LazyImportModule.AST_INDEX[INDEX_KEY][signature] module_name = mod_index[MODULE_KEY] + if module_name in LazyImportModule.AST_INDEX[REQUIREMENT_KEY]: + requirements = LazyImportModule.AST_INDEX[REQUIREMENT_KEY][ + module_name] + requires(module_name, requirements) importlib.import_module(module_name) else: logger.warning(f'{signature} not found in ast index file') diff --git a/requirements/cv.txt b/requirements/cv.txt index bd1a72db..661c96e4 100644 --- a/requirements/cv.txt +++ b/requirements/cv.txt @@ -1,4 +1,3 @@ -decord>=0.6.0 easydict # tensorflow 1.x compatability requires numpy version to be cap at 1.18 numpy<=1.18