Khắc phục sự cố

Thiếu đường dẫn tệp nhị phân Python

Thông báo lỗi:

ERROR: An error occurred during the fetch of repository 'local_execution_config_python':
  Traceback (most recent call last):
       File "/sandbox_path/external/org_tensorflow/third_party/py/python_configure.bzl", line 208
               get_python_bin(repository_ctx)
    ...
Repository command failed

thường cho biết Bazel không tìm thấy tệp nhị phân Python cục bộ. Để giải quyết vấn đề này, trước tiên, vui lòng tìm vị trí tệp nhị phân python, sau đó thêm --action_env PYTHON_BIN_PATH=<path to python binary> vào lệnh Bazel. Ví dụ: bạn có thể chuyển sang sử dụng tệp nhị phân python3 mặc định của hệ thống bằng lệnh sau:

bazel build -c opt \
  --define MEDIAPIPE_DISABLE_GPU=1 \
  --action_env PYTHON_BIN_PATH=$(which python3) \
  mediapipe/examples/desktop/hello_world

Thiếu các gói Python cần thiết

Thông báo lỗi:

ImportError: No module named numpy
Is numpy installed?

thường cho biết một số gói Python nhất định chưa được cài đặt. Vui lòng chạy pip install hoặc pip3 install tuỳ thuộc vào phiên bản tệp nhị phân Python để cài đặt các gói đó.

Không tìm nạp được kho lưu trữ phần phụ thuộc từ xa

Thông báo lỗi:

ERROR: An error occurred during the fetch of repository 'org_tensorflow':
   java.io.IOException: Error downloading [https://mirror.bazel.build/github.com/tensorflow/tensorflow/archive/77e9ffb9b2bfb1a4f7056e62d84039626923e328.tar.gz, https://github.com/tensorflow/tensorflow/archive/77e9ffb9b2bfb1a4f7056e62d84039626923e328.tar.gz] to /sandbox_path/external/org_tensorflow/77e9ffb9b2bfb1a4f7056e62d84039626923e328.tar.gz: Tried to reconnect at offset 9,944,151 but server didn't support it

or

WARNING: Download from https://storage.googleapis.com/mirror.tensorflow.org/github.com/bazelbuild/rules_swift/releases/download/0.12.1/rules_swift.0.12.1.tar.gz failed: class java.net.ConnectException Connection timed out (Connection timed out)

thường cho biết Bazel không tải được các kho lưu trữ phần phụ thuộc cần thiết mà MediaPipe cần. MediaPipe có một số kho lưu trữ phần phụ thuộc do các trang web của Google lưu trữ. Ở một số khu vực, bạn có thể cần thiết lập proxy mạng hoặc sử dụng VPN để truy cập vào các tài nguyên đó. Bạn cũng có thể cần thêm --host_jvm_args "-DsocksProxyHost=<ip address> -DsocksProxyPort=<port number>" vào lệnh Bazel. Hãy xem vấn đề này trên GitHub để biết thêm chi tiết.

Nếu bạn cho rằng đó không phải là vấn đề về mạng, thì khả năng khác là một số tài nguyên có thể tạm thời không hoạt động, vui lòng chạy bazel clean --expunge rồi thử lại sau. Nếu vẫn không giải quyết được vấn đề, vui lòng báo lỗi trên GitHub kèm theo thông báo lỗi chi tiết.

Cấu hình MediaPipe OpenCV không chính xác

Thông báo lỗi:

error: undefined reference to 'cv::String::deallocate()'
error: undefined reference to 'cv::String::allocate(unsigned long)'
error: undefined reference to 'cv::VideoCapture::VideoCapture(cv::String const&)'
...
error: undefined reference to 'cv::putText(cv::InputOutputArray const&, cv::String const&, cv::Point, int, double, cv::Scalar, int, int, bool)'

thường cho biết OpenCV chưa được định cấu hình đúng cách cho MediaPipe. Vui lòng xem các phần "Cài đặt OpenCV và FFmpeg" trong phần Cài đặt để biết cách sửa đổi WORKSPACE của MediaPipe và các tệp linux_opencv/macos_opencv/windows_opencv.BUILD cho thư viện opencv cục bộ. Vấn đề này trên GitHub cũng có thể giúp ích cho bạn.

Không cài đặt được Python pip

Thông báo lỗi:

ERROR: Could not find a version that satisfies the requirement mediapipe
ERROR: No matching distribution found for mediapipe

sau khi chạy pip install mediapipe thường cho biết rằng không có MediaPipe Python đủ điều kiện cho hệ thống của bạn. Xin lưu ý rằng MediaPipe Python PyPI chính thức hỗ trợ phiên bản 64 bit của Python 3.7 đến 3.10 trên các hệ điều hành sau:

  • Linux x86_64
  • x86_64 macOS 10.15 trở lên
  • Windows amd64

Nếu hệ điều hành hiện được hỗ trợ và bạn vẫn thấy lỗi này, vui lòng đảm bảo rằng cả tệp nhị phân Python và pip đều dành cho Python 3.7 đến 3.10. Nếu không, vui lòng cân nhắc tạo gói MediaPipe Python cục bộ bằng cách làm theo hướng dẫn tại đây.

Không tải được DLL Python trên Windows

Thông báo lỗi:

ImportError: DLL load failed: The specified module could not be found

thường cho biết hệ thống Windows cục bộ bị thiếu các gói Visual C++ có thể phân phối lại và/hoặc các DLL thời gian chạy Visual C++. Bạn có thể giải quyết vấn đề này bằng cách cài đặt vc_redist.x64.exe chính thức hoặc cài đặt gói Python "msvc-runtime" bằng cách chạy

$ python -m pip install msvc-runtime

Xin lưu ý rằng gói Python "msvc-runtime" không do Microsoft phát hành hoặc duy trì.

Không tìm thấy phương thức gốc

Thông báo lỗi:

java.lang.UnsatisfiedLinkError: No implementation found for void com.google.wick.Wick.nativeWick

thường cho biết một thư viện gốc cần thiết, chẳng hạn như /libwickjni.so chưa được tải hoặc chưa được đưa vào phần phụ thuộc của ứng dụng hoặc không tìm thấy vì lý do nào đó. Xin lưu ý rằng Java yêu cầu mọi thư viện gốc phải được tải rõ ràng bằng hàm System.loadLibrary.

Không tìm thấy máy tính đã đăng ký

Thông báo lỗi:

No registered object with name: OurNewCalculator; Unable to find Calculator "OurNewCalculator"

thường cho biết rằng OurNewCalculator được tham chiếu theo tên trong CalculatorGraphConfig nhưng mục tiêu thư viện cho OurNewCalculator chưa được liên kết với tệp nhị phân của ứng dụng. Khi thêm một máy tính mới vào biểu đồ máy tính, bạn cũng phải thêm máy tính đó làm phần phụ thuộc bản dựng của các ứng dụng sử dụng biểu đồ máy tính.

Lỗi này được phát hiện trong thời gian chạy vì biểu đồ máy tính tham chiếu máy tính theo tên thông qua trường CalculatorGraphConfig::Node:calculator. Khi thư viện cho máy tính được liên kết vào tệp nhị phân của ứng dụng, máy tính sẽ tự động được đăng ký theo tên thông qua macro REGISTER_CALCULATOR bằng cách sử dụng thư viện registration.h. Xin lưu ý rằng REGISTER_CALCULATOR có thể đăng ký một máy tính có tiền tố không gian tên giống với không gian tên C++. Trong trường hợp này, biểu đồ của máy tính cũng phải sử dụng cùng một tiền tố không gian tên.

Lỗi hết bộ nhớ

Tình trạng hết bộ nhớ có thể là triệu chứng của việc quá nhiều gói tích luỹ bên trong biểu đồ MediaPipe đang chạy. Điều này có thể xảy ra vì một số lý do, chẳng hạn như:

  1. Một số máy tính trong biểu đồ đơn giản là không thể theo kịp tốc độ đến của các gói từ luồng đầu vào theo thời gian thực, chẳng hạn như máy quay video.
  2. Một số máy tính đang chờ các gói không bao giờ đến.

Đối với vấn đề (1), bạn có thể cần phải loại bỏ một số gói cũ trong các gói cũ hơn để xử lý các gói gần đây hơn. Để biết một số gợi ý, hãy xem: How to process realtime input streams.

Đối với vấn đề (2), có thể một luồng đầu vào thiếu gói vì lý do nào đó. Thiết bị hoặc máy tính có thể được định cấu hình không chính xác hoặc chỉ tạo gói một cách không thường xuyên. Điều này có thể khiến các máy tính hạ nguồn phải chờ nhiều gói sẽ không bao giờ đến, từ đó khiến các gói tích luỹ trên một số luồng đầu vào của chúng. MediaPipe giải quyết loại vấn đề này bằng cách sử dụng "giới hạn dấu thời gian". Để biết một số gợi ý, hãy xem: How to process realtime input streams.

Chế độ cài đặt MediaPipe CalculatorGraphConfig::max_queue_size giới hạn số lượng gói được đưa vào hàng đợi trên bất kỳ luồng đầu vào nào bằng cách điều tiết đầu vào vào biểu đồ. Đối với luồng đầu vào theo thời gian thực, số lượng gói xếp hàng tại một luồng đầu vào hầu như luôn bằng 0 hoặc 1. Nếu không, bạn có thể thấy thông báo cảnh báo sau:

Resolved a deadlock by increasing max_queue_size of input stream

Ngoài ra, bạn có thể đặt chế độ cài đặt CalculatorGraphConfig::report_deadlock để khiến biểu đồ chạy không thành công và hiển thị tắc nghẽn dưới dạng lỗi, chẳng hạn như max_queue_size đóng vai trò là giới hạn sử dụng bộ nhớ.

Biểu đồ bị treo

Nhiều ứng dụng sẽ gọi CalculatorGraph::CloseAllPacketSourcesCalculatorGraph::WaitUntilDone để hoàn tất hoặc tạm ngưng thực thi biểu đồ MediaPipe. Mục tiêu ở đây là cho phép mọi máy tính hoặc gói đang chờ xử lý hoàn tất quá trình xử lý, sau đó tắt biểu đồ. Nếu mọi thứ diễn ra suôn sẻ, thì mọi luồng trong biểu đồ sẽ đạt đến Timestamp::Done và mọi máy tính sẽ đạt đến CalculatorBase::Close, sau đó CalculatorGraph::WaitUntilDone sẽ hoàn tất thành công.

Nếu một số máy tính hoặc luồng không thể đạt đến trạng thái Timestamp::Done hoặc CalculatorBase::Close, thì bạn có thể gọi phương thức CalculatorGraph::Cancel để chấm dứt quá trình chạy biểu đồ mà không cần chờ tất cả máy tính và gói đang chờ xử lý hoàn tất.

Thời gian đầu ra không đồng đều

Một số biểu đồ MediaPipe theo thời gian thực tạo ra một loạt khung hình video để xem dưới dạng hiệu ứng video hoặc dưới dạng chẩn đoán video. Đôi khi, biểu đồ MediaPipe sẽ tạo ra các khung hình này trong các cụm, chẳng hạn như khi một số khung hình đầu ra được ngoại suy từ cùng một cụm khung hình đầu vào. Nếu kết quả được trình bày khi được tạo, một số khung đầu ra sẽ được thay thế ngay lập tức bằng các khung sau đó trong cùng một cụm, khiến kết quả khó xem và đánh giá trực quan. Trong những trường hợp như vậy, bạn có thể cải thiện hình ảnh đầu ra bằng cách trình bày các khung hình theo khoảng thời gian đều đặn theo thời gian thực.

MediaPipe giải quyết trường hợp sử dụng này bằng cách liên kết dấu thời gian với các điểm theo thời gian thực. Mỗi dấu thời gian cho biết thời gian tính bằng micro giây và một máy tính như LiveClockSyncCalculator có thể trì hoãn đầu ra của các gói để khớp với dấu thời gian của các gói đó. Loại máy tính này điều chỉnh thời gian của đầu ra sao cho:

  1. Thời gian giữa các đầu ra tương ứng với thời gian giữa các dấu thời gian gần nhất có thể.
  2. Đầu ra được tạo với độ trễ nhỏ nhất có thể.

CalculatorGraph bị trễ so với dữ liệu đầu vào

Đối với nhiều biểu đồ MediaPipe theo thời gian thực, độ trễ thấp là một mục tiêu. MediaPipe hỗ trợ quy trình xử lý song song kiểu "quy trình" để bắt đầu xử lý từng gói càng sớm càng tốt. Thông thường, độ trễ thấp nhất có thể là tổng thời gian mà mỗi máy tính cần theo "đường dẫn quan trọng" của các máy tính kế tiếp. Độ trễ của biểu đồ MediaPipe có thể kém hơn mức lý tưởng do độ trễ được đưa vào để hiển thị khung hình theo khoảng thời gian đều đặn như mô tả trong phần Độ trễ đầu ra không đồng đều.

Nếu một số máy tính trong biểu đồ không thể bắt kịp luồng đầu vào theo thời gian thực, thì độ trễ sẽ tiếp tục tăng và bạn cần phải loại bỏ một số gói đầu vào. Kỹ thuật được đề xuất là sử dụng các máy tính MediaPipe được thiết kế riêng cho mục đích này, chẳng hạn như FlowLimiterCalculator như mô tả trong How to process realtime input streams.

Theo dõi dữ liệu đầu vào của máy tính và các giao dịch dàn xếp theo dấu thời gian

Để gỡ lỗi máy tính MediaPipe, bạn thường phải hiểu rõ về luồng dữ liệu và tính năng đồng bộ hoá dấu thời gian. Trước tiên, các gói đến cho máy tính sẽ được lưu vào bộ đệm trong hàng đợi đầu vào trên mỗi luồng để được InputStreamHandler được chỉ định đồng bộ hoá. Công việc của InputStreamHandler là xác định gói đầu vào được đặt cho một dấu thời gian đã được xác nhận, đưa máy tính vào trạng thái "sẵn sàng", sau đó kích hoạt lệnh gọi Calculator::Process với gói đầu vào đã xác định.

Bạn có thể dùng DebugInputStreamHandler để theo dõi các gói đến và các giao dịch thanh toán dấu thời gian theo thời gian thực trong đầu ra LOG(INFO) của ứng dụng. Bạn có thể chỉ định đối tượng này cho các máy tính cụ thể thông qua input_stream_handler của Máy tính hoặc biểu đồ trên toàn cầu thông qua trường input_stream_handler của CalculatorGraphConfig.

Trong quá trình thực thi biểu đồ, các gói đến sẽ tạo thông điệp LOG cho biết dấu thời gian và loại gói, theo sau là trạng thái hiện tại của tất cả hàng đợi đầu vào:

[INFO] SomeCalculator: Adding packet (ts:2, type:int) to stream INPUT_B:0:input_b
[INFO] SomeCalculator: INPUT_A:0:input_a num_packets: 0 min_ts: 2
[INFO] SomeCalculator: INPUT_B:0:input_b num_packets: 1 min_ts: 2

Ngoài ra, tính năng này cho phép giám sát các sự kiện dàn xếp dấu thời gian (trong trường hợp áp dụng DefaultInputStreamHandler). Điều này có thể giúp tiết lộ sự gia tăng giới hạn dấu thời gian không mong muốn trên các luồng đầu vào, dẫn đến lệnh gọi Calculator::Process với tập hợp đầu vào chưa hoàn chỉnh, dẫn đến các gói trống trên luồng đầu vào (có thể bắt buộc).

Tình huống mẫu:

node {
  calculator: "SomeCalculator"
  input_stream: "INPUT_A:a"
  input_stream: "INPUT_B:b"
  ...
}

Cho một máy tính có hai đầu vào, nhận một gói đến có dấu thời gian 1 trên luồng A, theo sau là một gói đầu vào có dấu thời gian 2 trên luồng B. Giới hạn dấu thời gian tăng lên 2 trên luồng B với gói đầu vào đang chờ xử lý trên luồng A tại dấu thời gian 1 kích hoạt lệnh gọi Calculator::Process với một tập hợp đầu vào chưa hoàn chỉnh cho dấu thời gian 1. Trong trường hợp này, DefaultInputStreamHandler sẽ xuất ra:

[INFO] SomeCalculator: Filled input set at ts: 1 with MISSING packets in input streams: INPUT_B:0:input_b.

VLOG là bạn đồng hành của bạn

MediaPipe sử dụng VLOG ở nhiều nơi để ghi lại các sự kiện quan trọng cho mục đích gỡ lỗi, đồng thời không ảnh hưởng đến hiệu suất nếu bạn không bật tính năng ghi nhật ký.

Xem thêm về VLOG trên abseil VLOG

Xin lưu ý rằng VLOG có thể là nội dung rác nếu bạn bật tính năng này trên toàn cục, ví dụ: (sử dụng cờ --v). Cờ --vmodule của giải pháp cho phép đặt các cấp độ khác nhau cho các tệp nguồn khác nhau.

Trong trường hợp không thể sử dụng --v / --vmodule (ví dụ: chạy ứng dụng Android), MediaPipe cho phép đặt chế độ ghi đè cờ VLOG --v / --vmodule cho mục đích gỡ lỗi được áp dụng khi tạo CalculatorGraph.

Ghi đè:

  • MEDIAPIPE_VLOG_V: xác định và cung cấp giá trị mà bạn cung cấp cho --v
  • MEDIAPIPE_VLOG_VMODULE: xác định và cung cấp giá trị mà bạn cung cấp cho --vmodule

Bạn có thể đặt chế độ ghi đè bằng cách thêm: --copt=-DMEDIAPIPE_VLOG_VMODULE=\"*calculator*=5\"

với các mẫu mô-đun và cấp VLOG mong muốn (xem thêm thông tin chi tiết về --vmodule tại abseil VLOG) vào lệnh bản dựng.

LƯU Ý QUAN TRỌNG: hãy lưu ý rằng việc thêm nội dung trên vào lệnh bản dựng sẽ kích hoạt quá trình tạo lại toàn bộ tệp nhị phân, bao gồm cả các phần phụ thuộc. Vì vậy, xét đến việc ghi đè VLOG chỉ tồn tại cho mục đích gỡ lỗi, bạn chỉ cần sửa đổi vlog_overrides.cc bằng cách thêm MEDIAPIPE_VLOG_V/VMODULE ở trên cùng.

Cờ không được hỗ trợ trong quá trình tạo bản dựng

Nếu đang sử dụng Clang 18 trở xuống, bạn có thể phải tắt một số tính năng tối ưu hoá trình biên dịch trong phần phụ trợ CPU của chúng tôi.

Để tắt tính năng hỗ trợ cho avxvnniint8, hãy thêm nội dung sau vào .bazelrc:

build --define=xnn_enable_avxvnniint8=false