image_editor_task.py 2.9 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576
  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 not os.path.isfile(out_file):
  30. raise RuntimeError(f"Output file not found: {output_path}")
  31. file_size = os.path.getsize(out_file)
  32. logger.info("[image_editor] Completed: output=%s (%.1f KB) in %.2fs",
  33. output_path, file_size / 1024, time.time() - t0)
  34. return TaskResult.success({"images": [output_path]})
  35. except Exception as e:
  36. logger.error("[image_editor] Failed in %.2fs: %s", time.time() - t0, e, exc_info=True)
  37. return TaskResult.failure(str(e))
  38. @staticmethod
  39. def _execute_p2p(images: list[str], effect_dir: str, output_path: str, workspace: str):
  40. cmd_parts = ["./p2pconvertor"]
  41. for img in images:
  42. cmd_parts.extend(["-i", img])
  43. cmd_parts.extend(["-e", effect_dir, "-o", output_path])
  44. cmd_str = " ".join(cmd_parts)
  45. logger.info("[image_editor] Executing: %s (cwd=%s)", cmd_str, workspace)
  46. cmd_t0 = time.time()
  47. result = subprocess.run(
  48. ["sh", "-c", cmd_str],
  49. cwd=workspace, capture_output=True, text=True,
  50. )
  51. cmd_elapsed = time.time() - cmd_t0
  52. if result.stdout:
  53. logger.info("[image_editor] stdout: %s", result.stdout.strip())
  54. if result.stderr:
  55. logger.warning("[image_editor] stderr: %s", result.stderr.strip())
  56. if result.returncode != 0:
  57. logger.error("[image_editor] p2pconvertor failed: exit_code=%d in %.2fs", result.returncode, cmd_elapsed)
  58. raise RuntimeError(f"p2pconvertor failed with exit code {result.returncode}")
  59. logger.info("[image_editor] p2pconvertor completed: exit_code=0 in %.2fs", cmd_elapsed)