image_editor_task.py 2.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475
  1. import logging
  2. import os
  3. import subprocess
  4. import time
  5. from typing import Any
  6. from app.service.task.base_task import BaseTask
  7. from app.service.task.task_param import TaskParam
  8. from app.service.task.task_result import TaskResult
  9. from app.util.file_util import copy_file
  10. from app.util.res_util import get_resources_path
  11. logger = logging.getLogger(__name__)
  12. class ImageEditorTask(BaseTask):
  13. def get_type(self) -> str:
  14. return "image_editor"
  15. def execute(self, param: TaskParam) -> TaskResult:
  16. images_obj = param.inputs.get("images")
  17. images: list[str] = images_obj if isinstance(images_obj, list) else []
  18. logger.info("[image_editor] Starting: %d images, resources=%s", len(images), param.resources)
  19. t0 = time.time()
  20. try:
  21. src = os.path.join(get_resources_path(), "image_editor", "p2pconvertor")
  22. dst = os.path.join(param.workspace, "p2pconvertor")
  23. copy_file(src, dst)
  24. os.chmod(dst, 0o755)
  25. logger.info("[image_editor] Copied p2pconvertor to workspace")
  26. output_path = f"{param.step_id}/output.jpg"
  27. self._execute_p2p(images, param.resources, output_path, param.workspace)
  28. out_file = os.path.join(param.workspace, output_path)
  29. if os.path.isfile(out_file):
  30. file_size = os.path.getsize(out_file)
  31. logger.info("[image_editor] Completed: output=%s (%.1f KB) in %.2fs",
  32. output_path, file_size / 1024, time.time() - t0)
  33. else:
  34. logger.warning("[image_editor] Completed but output file not found: %s", output_path)
  35. return TaskResult.success({"images": [output_path]})
  36. except Exception as e:
  37. logger.error("[image_editor] Failed in %.2fs: %s", time.time() - t0, e, exc_info=True)
  38. return TaskResult.failure(str(e))
  39. @staticmethod
  40. def _execute_p2p(images: list[str], effect_dir: str, output_path: str, workspace: str):
  41. cmd_parts = ["./p2pconvertor"]
  42. for img in images:
  43. cmd_parts.extend(["-i", img])
  44. cmd_parts.extend(["-e", effect_dir, "-o", output_path])
  45. cmd_str = " ".join(cmd_parts)
  46. logger.info("[image_editor] Executing: %s (cwd=%s)", cmd_str, workspace)
  47. cmd_t0 = time.time()
  48. result = subprocess.run(
  49. ["sh", "-c", cmd_str],
  50. cwd=workspace, capture_output=True, text=True,
  51. )
  52. cmd_elapsed = time.time() - cmd_t0
  53. if result.stdout:
  54. logger.info("[image_editor] stdout: %s", result.stdout.strip())
  55. if result.stderr:
  56. logger.warning("[image_editor] stderr: %s", result.stderr.strip())
  57. if result.returncode != 0:
  58. logger.error("[image_editor] p2pconvertor failed: exit_code=%d in %.2fs", result.returncode, cmd_elapsed)
  59. else:
  60. logger.info("[image_editor] p2pconvertor completed: exit_code=0 in %.2fs", cmd_elapsed)