{"id":40,"date":"2026-03-29T03:11:35","date_gmt":"2026-03-29T03:11:35","guid":{"rendered":"https:\/\/melona.shop\/?p=40"},"modified":"2026-06-28T12:13:43","modified_gmt":"2026-06-28T12:13:43","slug":"%ed%9a%8c%ea%b0%80%ec%a0%81%ec%9c%a0%ed%98%b9-%ec%9e%90%eb%a7%89-%ed%95%9c%ea%b8%80%c2%b7%ec%8b%b1%ed%81%ac-%eb%a7%9e%ec%b6%a4%c2%b7%ec%a7%81%ec%a0%91-%ec%a0%9c%ec%9e%91","status":"publish","type":"post","link":"https:\/\/melona.shop\/?p=40","title":{"rendered":"\ud68c\uac00\uc801\uc720\ud639 \uc790\ub9c9 (\ud55c\uae00\u00b7\uc2f1\ud06c \ub9de\ucda4\u00b7\uc9c1\uc811 \uc81c\uc791)"},"content":{"rendered":"\n<figure class=\"wp-block-image size-large\"><img loading=\"lazy\" decoding=\"async\" width=\"1024\" height=\"683\" src=\"https:\/\/melona.shop\/wp-content\/uploads\/2026\/06\/\uc2a4\ud06c\ub9b0\uc0f7159-1024x683.png\" alt=\"\" class=\"wp-image-41\" srcset=\"https:\/\/melona.shop\/wp-content\/uploads\/2026\/06\/\uc2a4\ud06c\ub9b0\uc0f7159-1024x683.png 1024w, https:\/\/melona.shop\/wp-content\/uploads\/2026\/06\/\uc2a4\ud06c\ub9b0\uc0f7159-300x200.png 300w, https:\/\/melona.shop\/wp-content\/uploads\/2026\/06\/\uc2a4\ud06c\ub9b0\uc0f7159-768x512.png 768w, https:\/\/melona.shop\/wp-content\/uploads\/2026\/06\/\uc2a4\ud06c\ub9b0\uc0f7159-1536x1024.png 1536w, https:\/\/melona.shop\/wp-content\/uploads\/2026\/06\/\uc2a4\ud06c\ub9b0\uc0f7159-2048x1365.png 2048w\" sizes=\"auto, (max-width: 1024px) 100vw, 1024px\" \/><\/figure>\n\n\n\n<figure class=\"wp-block-image size-large\"><img loading=\"lazy\" decoding=\"async\" width=\"1024\" height=\"683\" src=\"https:\/\/melona.shop\/wp-content\/uploads\/2026\/06\/\uc2a4\ud06c\ub9b0\uc0f7160-1024x683.png\" alt=\"\" class=\"wp-image-42\" srcset=\"https:\/\/melona.shop\/wp-content\/uploads\/2026\/06\/\uc2a4\ud06c\ub9b0\uc0f7160-1024x683.png 1024w, https:\/\/melona.shop\/wp-content\/uploads\/2026\/06\/\uc2a4\ud06c\ub9b0\uc0f7160-300x200.png 300w, https:\/\/melona.shop\/wp-content\/uploads\/2026\/06\/\uc2a4\ud06c\ub9b0\uc0f7160-768x512.png 768w, https:\/\/melona.shop\/wp-content\/uploads\/2026\/06\/\uc2a4\ud06c\ub9b0\uc0f7160-1536x1024.png 1536w, https:\/\/melona.shop\/wp-content\/uploads\/2026\/06\/\uc2a4\ud06c\ub9b0\uc0f7160-2048x1365.png 2048w\" sizes=\"auto, (max-width: 1024px) 100vw, 1024px\" \/><\/figure>\n\n\n\n<p class=\"wp-block-paragraph\">\u56de\u5bb6\u7684\u8bf1\u60d1(<strong>Simplified Chinese<\/strong>)<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">\u56de\u5bb6\u7684\u8a98\u60d1(<strong>Traditional Chinese<\/strong>)<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">\uc81c\uc791\ud558\ub294 \ub300\ub85c \ud558\ub098\ud558\ub098 \uc5c5\ub85c\ub4dc \ud569\ub2c8\ub2e4.<\/p>\n\n\n\n<hr class=\"wp-block-separator has-alpha-channel-opacity\"\/>\n\n\n\n<div class=\"wp-block-file\"><a id=\"wp-block-file--media-612a012c-d603-4877-873b-464c0bc59262\" href=\"https:\/\/melona.shop\/wp-content\/uploads\/2026\/03\/Home.Temptation.2011.S01E01.1080p.WEB-DL.H264.AAC.Mandarin.srt\">Home.Temptation.2011.S01E01.1080p.WEB-DL.H264.AAC.Mandarin<\/a><a href=\"https:\/\/melona.shop\/wp-content\/uploads\/2026\/03\/Home.Temptation.2011.S01E01.1080p.WEB-DL.H264.AAC.Mandarin.srt\" class=\"wp-block-file__button wp-element-button\" download aria-describedby=\"wp-block-file--media-612a012c-d603-4877-873b-464c0bc59262\">\ub2e4\uc6b4\ub85c\ub4dc<\/a><\/div>\n\n\n\n<div class=\"wp-block-file\"><a id=\"wp-block-file--media-8dcf4cba-4796-4050-8f7c-591d35206de3\" href=\"https:\/\/melona.shop\/wp-content\/uploads\/2026\/03\/Home.Temptation.2011.S01E02.1080p.WEB-DL.H264.AAC.Mandarin.srt\">Home.Temptation.2011.S01E02.1080p.WEB-DL.H264.AAC.Mandarin<\/a><a href=\"https:\/\/melona.shop\/wp-content\/uploads\/2026\/03\/Home.Temptation.2011.S01E02.1080p.WEB-DL.H264.AAC.Mandarin.srt\" class=\"wp-block-file__button wp-element-button\" download aria-describedby=\"wp-block-file--media-8dcf4cba-4796-4050-8f7c-591d35206de3\">\ub2e4\uc6b4\ub85c\ub4dc<\/a><\/div>\n\n\n\n<hr class=\"wp-block-separator has-alpha-channel-opacity\"\/>\n\n\n\n<pre class=\"wp-block-code\"><code>import os\nimport glob\nimport cv2\nimport logging\nfrom paddleocr import PaddleOCR\nfrom datetime import timedelta\n\n# \ubd88\ud544\uc694\ud55c \ub0b4\ubd80 \ub85c\uadf8 \uc228\uae30\uae30\nlogging.getLogger(\"ppocr\").setLevel(logging.ERROR)\n\ndef format_timedelta(td):\n    \"\"\"\ucd08(second)\ub97c SRT \ud45c\uc900 \uc2dc\uac04 \ud3ec\ub9f7(HH:MM:SS,mmm)\uc73c\ub85c \ubcc0\ud658\"\"\"\n    total_seconds = int(td.total_seconds())\n    milliseconds = int(td.microseconds \/ 1000)\n    hours = total_seconds \/\/ 3600\n    minutes = (total_seconds % 3600) \/\/ 60\n    seconds = total_seconds % 60\n    return f\"{hours:02d}:{minutes:02d}:{seconds:02d},{milliseconds:03d}\"\n\ndef extract_chinese_subtitles(video_path, lang='ch', output_file='subtitles.srt'):\n    print(f\"\ud83d\udd25 &#91;{video_path}] \uc790\ub9c9 \ucd94\ucd9c \uc2dc\uc791!\")\n    \n    ocr = PaddleOCR(use_angle_cls=False, lang=lang)\n    cap = cv2.VideoCapture(video_path)\n    \n    if not cap.isOpened():\n        print(f\"\u274c {video_path} \ub3d9\uc601\uc0c1\uc744 \uc5f4 \uc218 \uc5c6\uc2b5\ub2c8\ub2e4.\")\n        return\n\n    fps = cap.get(cv2.CAP_PROP_FPS)\n    frame_interval = int(fps \/ 2)\n    frame_count = 0\n    \n    current_text = \"\"\n    start_time = 0\n    subtitle_index = 1\n    \n    # 'w' \ubaa8\ub4dc\ub85c \ud30c\uc77c \uc5f4\uae30 (utf-8 \uc778\ucf54\ub529 \ud544\uc218)\n    with open(output_file, 'w', encoding='utf-8') as f:\n        while cap.isOpened():\n            ret, frame = cap.read()\n            if not ret:\n                # \uc601\uc0c1\uc774 \ub05d\ub0ac\uc744 \ub54c \ub9c8\uc9c0\ub9c9\uc73c\ub85c \ud654\uba74\uc5d0 \uc788\ub358 \uc790\ub9c9 \uae30\ub85d\n                if current_text:\n                    end_time = cap.get(cv2.CAP_PROP_POS_MSEC) \/ 1000.0\n                    f.write(f\"{subtitle_index}\\n\")\n                    f.write(f\"{format_timedelta(timedelta(seconds=start_time))} --> {format_timedelta(timedelta(seconds=end_time))}\\n\")\n                    f.write(f\"{current_text}\\n\\n\")\n                break\n\n            if frame_count % frame_interval == 0:\n                height, width, _ = frame.shape\n                # \ud654\uba74 \ud558\ub2e8 25% \uc601\uc5ed\ub9cc \ud06c\ub86d\ud558\uc5ec OCR \uc778\uc2dd \uc18d\ub3c4 \ubc0f \uc815\ud655\ub3c4 \ud5a5\uc0c1\n                crop_h_start = int(height * 0.75)\n                cropped_frame = frame&#91;crop_h_start:height, 0:width]\n\n                result = ocr.ocr(cropped_frame, cls=False)\n                \n                frame_text = \"\"\n                if result and result&#91;0]:\n                    frame_text = \"\".join(&#91;line&#91;1]&#91;0] for line in result&#91;0]]).strip()\n                \n                # \ud654\uba74\uc758 \ud14d\uc2a4\ud2b8\uac00 \uc774\uc804\uacfc \ub2ec\ub77c\uc84c\uc744 \ub54c (\uc0c8 \uc790\ub9c9 \ub4f1\uc7a5 or \uc790\ub9c9 \uc0ac\ub77c\uc9d0)\n                if frame_text != current_text:\n                    current_time_sec = frame_count \/ fps\n                    \n                    # \ubc29\uae08 \uc804\uae4c\uc9c0 \ud654\uba74\uc5d0 \uc788\ub358 \uc790\ub9c9\uc744 \ud30c\uc77c\uc5d0 \uae30\ub85d\n                    if current_text:\n                        end_time = current_time_sec\n                        f.write(f\"{subtitle_index}\\n\")\n                        f.write(f\"{format_timedelta(timedelta(seconds=start_time))} --> {format_timedelta(timedelta(seconds=end_time))}\\n\")\n                        f.write(f\"{current_text}\\n\\n\")\n                        subtitle_index += 1\n                    \n                    # \uc0c8\ub85c\uc6b4 \uc790\ub9c9 \uc0c1\ud0dc\ub85c \uc5c5\ub370\uc774\ud2b8\n                    current_text = frame_text\n                    start_time = current_time_sec\n                    \n                    # \ud130\ubbf8\ub110\uc5d0\ub3c4 \uc9c4\ud589 \uc0c1\ud669 \ucd9c\ub825\n                    if current_text:\n                        print(f\"&#91;{format_timedelta(timedelta(seconds=start_time))}] {current_text}\")\n\n            frame_count += 1\n\n    cap.release()\n    print(f\"\ud83c\udf89 \ucd94\ucd9c \uc644\ub8cc! '{output_file}' \ud30c\uc77c\uc774 \uc0dd\uc131\ub418\uc5c8\uc2b5\ub2c8\ub2e4.\\n\")\n\n\n# --- \uba54\uc778 \uc2e4\ud589\ubd80 ---\nif __name__ == \"__main__\":\n    # \ud604\uc7ac \ud3f4\ub354\uc5d0 \uc788\ub294 \ubaa8\ub4e0 .mp4 \ud30c\uc77c\uc744 \uc790\ub3d9\uc73c\ub85c \ucc3e\uc544 \ub9ac\uc2a4\ud2b8\ub85c \ub9cc\ub4ed\ub2c8\ub2e4.\n    video_files = glob.glob('*.mp4')\n\n    if not video_files:\n        print(\"\u274c \ucc98\ub9ac\ud560 MP4 \ud30c\uc77c\uc774 \ud604\uc7ac \uc2a4\ud06c\ub9bd\ud2b8\uac00 \uc788\ub294 \ud3f4\ub354\uc5d0 \uc5c6\uc2b5\ub2c8\ub2e4.\")\n    else:\n        print(f\"\ucd1d {len(video_files)}\uac1c\uc758 \ud30c\uc77c\uc744 \uc21c\ucc28\uc801\uc73c\ub85c \uc791\uc5c5\ud569\ub2c8\ub2e4.\\n\")\n        print(\"=\" * 50)\n        \n        # for\ubb38\uc744 \uc0ac\uc6a9\ud558\uc5ec \ub9ac\uc2a4\ud2b8 \uc548\uc758 \ud30c\uc77c\uc744 \ud558\ub098\uc529 \uc21c\ucc28\uc801\uc73c\ub85c \uaebc\ub0b4\uc11c \uc791\uc5c5\n        for video_file in video_files:\n            # \ud30c\uc77c \uc774\ub984\uc5d0\uc11c \ud655\uc7a5\uc790(.mp4)\ub97c \ubd84\ub9ac\ud558\uc5ec \uc6d0\ubcf8 \ud30c\uc77c\uba85\ub9cc \ucd94\ucd9c\n            base_name = os.path.splitext(video_file)&#91;0]\n            \n            # \ucd9c\ub825\ud560 srt \ud30c\uc77c \uc774\ub984\uc744 \uc6d0\ubcf8 \uc601\uc0c1 \uc774\ub984\uacfc \ub3d9\uc77c\ud558\uac8c \uc124\uc815 (\uc608: \uc601\uc0c1\uc774\ub984.srt)\n            output_srt = f\"{base_name}.srt\"\n            \n            # \uc790\ub9c9 \ucd94\ucd9c \ud568\uc218 \uc2e4\ud589\n            extract_chinese_subtitles(video_file, lang='ch', output_file=output_srt)\n            \n            # \uc791\uc5c5 \uad6c\ubd84\uc744 \uc704\ud55c \uc808\ucde8\uc120 \ucd9c\ub825\n            print(\"-\" * 50) \n            \n        print(\"\u2705 \ubaa8\ub4e0 \uc601\uc0c1\uc758 \uc790\ub9c9 \ucd94\ucd9c \uc791\uc5c5\uc774 \uc131\uacf5\uc801\uc73c\ub85c \uc644\ub8cc\ub418\uc5c8\uc2b5\ub2c8\ub2e4!\")<\/code><\/pre>\n\n\n\n<p class=\"wp-block-paragraph\">Paddle OCR \uc744 \uc0ac\uc6a9\ud558\ub2c8 EasyOCR \ubcf4\ub2e4 \uc18d\ub3c4\ub3c4 \ube68\ub77c\uc9c0\uace0 \uc778\uc2dd\ub960\ub3c4 \uad49\uc7a5\ud788 \uc88b\uc544\uc84c\ub2e4.<\/p>\n","protected":false},"excerpt":{"rendered":"<p>\u56de\u5bb6\u7684\u8bf1\u60d1(Simplified Chinese) \u56de\u5bb6\u7684\u8a98\u60d1(Traditional Chinese) \uc81c\uc791\ud558\ub294 \ub300\ub85c \ud558\ub098\ud558\ub098 \uc5c5\ub85c\ub4dc \ud569\ub2c8\ub2e4. Paddle OCR \uc744 \uc0ac\uc6a9\ud558\ub2c8 EasyOCR \ubcf4\ub2e4 \uc18d\ub3c4\ub3c4 \ube68\ub77c\uc9c0\uace0 \uc778\uc2dd\ub960\ub3c4 \uad49\uc7a5\ud788 \uc88b\uc544\uc84c\ub2e4.<\/p>\n","protected":false},"author":1,"featured_media":0,"comment_status":"open","ping_status":"open","sticky":false,"template":"","format":"standard","meta":{"footnotes":""},"categories":[1],"tags":[],"class_list":["post-40","post","type-post","status-publish","format-standard","hentry","category-1"],"_links":{"self":[{"href":"https:\/\/melona.shop\/index.php?rest_route=\/wp\/v2\/posts\/40","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/melona.shop\/index.php?rest_route=\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/melona.shop\/index.php?rest_route=\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/melona.shop\/index.php?rest_route=\/wp\/v2\/users\/1"}],"replies":[{"embeddable":true,"href":"https:\/\/melona.shop\/index.php?rest_route=%2Fwp%2Fv2%2Fcomments&post=40"}],"version-history":[{"count":4,"href":"https:\/\/melona.shop\/index.php?rest_route=\/wp\/v2\/posts\/40\/revisions"}],"predecessor-version":[{"id":51,"href":"https:\/\/melona.shop\/index.php?rest_route=\/wp\/v2\/posts\/40\/revisions\/51"}],"wp:attachment":[{"href":"https:\/\/melona.shop\/index.php?rest_route=%2Fwp%2Fv2%2Fmedia&parent=40"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/melona.shop\/index.php?rest_route=%2Fwp%2Fv2%2Fcategories&post=40"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/melona.shop\/index.php?rest_route=%2Fwp%2Fv2%2Ftags&post=40"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}