Пример #1
0
def is_server():
    if os.path.isfile(ap.dl_server_dir + "1"):
        cm.clear_path(ap.dl_server_dir + "1")
        cm.queue_append(ap.dl_server_dir + "2")
        return APP_SERVER_2
    else:
        cm.clear_path(ap.dl_server_dir + "2")
        cm.queue_append(ap.dl_server_dir + "1")
        return APP_SERVER_1
Пример #2
0
def do_analyze():
    # 変数不足時は終了
    if not sys.argv[1]:
        return

    youtube_url = sys.argv[1]

    # ID部分の取り出し
    youtube_id = al.get_youtube_id(youtube_url)
    if not youtube_id:
        return

    cached = cm.cache_check(youtube_id)

    # 5分経過した3xx キャッシュ以外は再解析しない
    if cached:
        return

    queue_path = ap.queue_dir + str(youtube_id)
    pending_path = ap.pending_dir + str(youtube_id)

    url = "http://" + is_server() + "/rest/analyze?Url=" + youtube_url

    req = urllib.request.Request(url)
    try:
        with urllib.request.urlopen(req) as res:
            body = json.load(res)

            title = body.get("result").get("title")
            time_line = body.get("result").get("timeline")
            time_line_enemy = body.get("result").get("timeline_enemy")
            total_damage = body.get("result").get("total_damage")
            debuff_value = body.get("result").get("debuff_value")
            url_result = body.get("status")
    except HTTPError:
        title = ""
        url_result = state.ERR_APP_SERVER_HTTP
    except URLError:
        title = ""
        url_result = state.ERR_APP_SERVER_URL
    except TimeoutError:
        title = ""
        url_result = state.ERR_ANALYZE_TIMEOUT

    if url_result % 100 // 10 == 2:
        cm.save_cache(youtube_id, title, False, False, False, False, False,
                      url_result)
    else:
        # キャッシュ保存
        cm.save_cache(youtube_id, title, time_line, time_line_enemy, False,
                      total_damage, debuff_value, url_result)

    cm.clear_path(queue_path)
    cm.clear_path(pending_path)
Пример #3
0
def search(youtube_id):
    """get movie from youtube

    get movie from YouTube iTag 22 (720p / mp4) or iTag 18 (360p / mp4)

    Args:
        youtube_id (str): user input youtube_id

    Returns:
        movie_path (str): movie save path
        movie_title (str): movie title
        movie_length (str): movie length
        movie_thumbnail (str): movie thumbnail url
        status (str): error status while get movie


    """
    # add dl ongoing queue
    dl_ongoing_path = ap.dl_ongoing_dir + str(youtube_id)
    cm.queue_append(dl_ongoing_path)

    youtube_url = "https://www.youtube.com/watch?v=" + youtube_id

    try:
        # add dl pending queue
        dl_pending_path = ap.dl_pending_dir + "pending"
        cm.queue_append(dl_pending_path)
        yt = YouTube(youtube_url)
    except:
        cm.clear_path(dl_ongoing_path)
        return None, None, None, None, state.TMP_CANT_GET_HD

    movie_thumbnail = yt.thumbnail_url
    movie_length = yt.length
    if int(movie_length) > MOVIE_LENGTH_MAX:
        cm.clear_path(dl_ongoing_path)
        return None, None, None, None, state.ERR_BAD_LENGTH

    status = state.DONE
    stream = yt.streams.get_by_itag(22)
    if stream is None:
        status = state.TMP_DONE_IN_SD
        stream = yt.streams.get_by_itag(18)
        if stream is None:
            cm.clear_path(dl_ongoing_path)
            return None, None, None, None, state.ERR_BAD_RESOLUTION

    movie_title = stream.title
    movie_name = tm.time()
    movie_path = stream.download(ap.stream_dir, str(movie_name))

    cm.clear_path(dl_ongoing_path)

    return movie_path, movie_title, movie_length, movie_thumbnail, status
Пример #4
0
def do_analyze():
    # 変数不足時は終了
    if not sys.argv[1]:
        return

    youtube_url = sys.argv[1]

    # ID部分の取り出し
    youtube_id = al.get_youtube_id(youtube_url)
    if not youtube_id:
        return

    cached = cm.cache_check(youtube_id)

    # 5分経過した3xx キャッシュ以外は再解析しない
    if cached:
        return

    queue_path = ap.queue_dir + str(youtube_id)
    pending_path = ap.pending_dir + str(youtube_id)

    # youtube動画検索/検証
    path, title, length, thumbnail, url_result = al.search(youtube_id)
    if url_result % 100 // 10 == 2:
        cm.save_cache(youtube_id, title, False, False, False, False, False,
                      url_result)
    else:
        # TL解析
        time_line, time_line_enemy, time_data, total_damage, debuff_value, analyze_result = al.analyze_movie(
            path)
        # キャッシュ保存
        cm.save_cache(youtube_id, title, time_line, time_line_enemy, False,
                      total_damage, debuff_value, analyze_result)

    cm.clear_path(queue_path)
    cm.clear_path(pending_path)
Пример #5
0
def index():
    if request.method == "POST":
        url = (request.form["Url"])

        # urlからid部分の抽出
        youtube_id = an.get_youtube_id(url)
        if youtube_id is False:
            error = el.get_error_message(el.ERR_BAD_URL)
            return render_template("index.html", error=error)

        cache = cm.cache_check(youtube_id)

        if cache is not False:
            title, time_line, time_data, total_damage, debuff_value, past_status = cache
            if past_status // 100 == 2:
                debuff_dict, data_txt, data_url, total_damage = get_web_txt(youtube_id, title,
                                                                            time_line, debuff_value, total_damage)

                return render_template("result.html", title=title, timeLine=time_line,
                                       timeData=time_data, totalDamage=total_damage, debuffDict=debuff_dict,
                                       data_txt=data_txt, data_url=data_url)

            elif past_status // 100 == 3:
                pass
            else:
                error = el.get_error_message(past_status)
                return render_template("index.html", error=error)

        path, title, length, thumbnail, url_result = an.search(youtube_id)

        if url_result // 100 == 4:
            error = el.get_error_message(url_result)
            cm.save_cache(youtube_id, title, False, False, False, False, url_result)
            return render_template("index.html", error=error)

        elif url_result == el.ERR_CANT_GET_HD:
            error = el.get_error_message(url_result)
            return render_template("index.html", error=error)

        session["path"] = path
        session["title"] = title
        session["youtube_id"] = youtube_id
        length = int(int(length) / 8) + 3

        return render_template("analyze.html", title=title, length=length, thumbnail=thumbnail)

    elif request.method == "GET":
        if "v" in request.args:  # ?v=YoutubeID 形式のGETであればリザルト返却
            youtube_id = request.args.get("v")
            if re.fullmatch(r"^([a-zA-Z0-9_-]{11})$", youtube_id):
                cache = cm.cache_check(youtube_id)
                if cache is not False:
                    title, time_line, time_data, total_damage, debuff_value, past_status = cache
                    if past_status // 100 == 2:
                        debuff_dict, data_txt, data_url, total_damage = get_web_txt(youtube_id, title,
                                                                                    time_line, debuff_value,
                                                                                    total_damage)

                        return render_template("result.html", title=title, timeLine=time_line,
                                               timeData=time_data, totalDamage=total_damage, debuffDict=debuff_dict,
                                               data_txt=data_txt, data_url=data_url)

                    elif past_status // 100 == 3:
                        pass

                    else:
                        error = el.get_error_message(past_status)
                        return render_template("index.html", error=error)

                else:  # キャッシュが存在しない場合は解析
                    path, title, length, thumbnail, url_result = an.search(youtube_id)

                    if url_result // 100 == 4:
                        error = el.get_error_message(url_result)
                        cm.save_cache(youtube_id, title, False, False, False, False, url_result)
                        return render_template("index.html", error=error)

                    elif url_result == el.ERR_CANT_GET_HD:
                        error = el.get_error_message(url_result)
                        return render_template("index.html", error=error)

                    session["path"] = path
                    session["title"] = title
                    session["youtube_id"] = youtube_id
                    length = int(int(length) / 8) + 3

                    return render_template("analyze.html", title=title, length=length, thumbnail=thumbnail)

            else:  # prilog.jp/(YoutubeID)に該当しないリクエスト
                error = "不正なリクエストです"
                return render_template("index.html", error=error)
            
        else:
            path = session.get("path")
            session.pop("path", None)
            session.pop("title", None)
            session.pop("youtube_id", None)

            error = None
            if path is el.ERR_BAD_RESOLUTION:
                error = el.get_error_message(path)

            elif path is not None:
                cm.clear_path(path)

            return render_template("index.html", error=error)
Пример #6
0
def rest_analyze():
    status = el.DONE
    rest_result = {}
    ret = {}
    url = ""
    if request.method == "POST":
        if "Url" not in request.form:
            status = el.ERR_BAD_REQ

            ret["result"] = rest_result
            ret["msg"] = el.get_error_message(status)
            ret["status"] = status
            return jsonify(ret)
        else:
            url = request.form["Url"]

    elif request.method == "GET":
        if "Url" not in request.args:
            status = el.ERR_BAD_REQ

            ret["result"] = rest_result
            ret["msg"] = el.get_error_message(status)
            ret["status"] = status
            return jsonify(ret)
        else:
            url = request.args.get("Url")

    # キャッシュ確認
    youtube_id = an.get_youtube_id(url)
    if youtube_id is False:
        # 不正なurlの場合
        status = el.ERR_BAD_URL
    else:
        # 正常なurlの場合
        cache = cm.cache_check(youtube_id)

        if cache is not False:
            # キャッシュ有りの場合
            # キャッシュを返信
            title, time_line, time_data, total_damage, debuff_value, past_status = cache
            if past_status // 100 == 2:
                rest_result = get_rest_result(title, time_line, time_data, total_damage, debuff_value)

                ret["result"] = rest_result
                ret["msg"] = el.get_error_message(past_status)
                ret["status"] = past_status
                return jsonify(ret)

            elif (past_status // 100) == 3:
                pass
            else:
                ret["result"] = rest_result
                ret["msg"] = el.get_error_message(past_status)
                ret["status"] = past_status
                return jsonify(ret)

        # start analyze
        # 既にキューに登録されているか確認
        queue_path = queue_dir + str(youtube_id)
        pending_path = pending_dir + str(youtube_id)
        queued = os.path.exists(queue_path)
        if queued:  # 既に解析中の場合
            while True:  # キューが消えるまで監視
                # 暫定的実装
                # 監視中にキューが30分以上残置されているのを見つけると削除する
                try:
                    now = datetime.date.today()  # 現在の時刻を取得
                    timestamp = datetime.date.fromtimestamp(int(os.path.getmtime(queue_path)))

                    if (now - timestamp).seconds >= 30 * 60:  # 30分経過してたら削除
                        cm.clear_path(queue_path)
                        cm.clear_path(pending_path)

                except FileNotFoundError:
                    pass

                queued = os.path.exists(queue_path)
                if queued:
                    tm.sleep(1)
                    continue
                else:  # 既に開始されている解析が完了したら、そのキャッシュJSONを返す
                    cache = cm.cache_check(youtube_id)
                    if cache is not False:
                        title, time_line, time_data, total_damage, debuff_value, past_status = cache
                        if past_status // 100 == 2 or past_status // 100 == 3:
                            rest_result = get_rest_result(title, time_line, time_data, total_damage, debuff_value)

                        status = past_status
                        break
                    else:  # キャッシュ未生成の場合
                        # キャッシュを書き出してから解析キューから削除されるため、本来起こり得ないはずのエラー
                        status = el.ERR_UNEXPECTED
                        break

        else:  # 既に解析中ではない場合
            # 解析キューに登録
            cm.queue_append(queue_path)

            # キューが回ってきたか確認し、来たら解析実行
            while True:
                if not cm.is_pending_exists() and cm.is_queue_current(queue_path):
                    # pendingに登録
                    pending_path = pending_dir + str(youtube_id)
                    cm.pending_append(pending_path)
                    # youtube動画検索/検証
                    path, title, length, thumbnail, url_result = an.search(youtube_id)
                    status = url_result
                    if url_result // 100 == 4:
                        cm.save_cache(youtube_id, title, False, False, False, False, url_result)
                    elif url_result == el.ERR_CANT_GET_HD:
                        pass
                    else:
                        # TL解析
                        time_line, time_data, total_damage, debuff_value, analyze_result = an.analyze_movie(path)
                        status = analyze_result
                        # キャッシュ保存
                        cm.save_cache(youtube_id, title, time_line, False, total_damage, debuff_value, status)

                        if analyze_result is el.DONE:
                            # 解析が正常終了ならば結果を格納
                            rest_result = get_rest_result(title, time_line, time_data, total_damage, debuff_value)

                    cm.clear_path(queue_path)
                    cm.clear_path(pending_path)
                    break

                tm.sleep(1)

    ret["result"] = rest_result
    ret["msg"] = el.get_error_message(status)
    ret["status"] = status
    return jsonify(ret)
Пример #7
0
def index():
    if request.method == "POST":
        url = (request.form["Url"])

        # urlからid部分の抽出
        youtube_id = al.get_youtube_id(url)
        if youtube_id is False:
            error = state.get_error_message(state.ERR_BAD_URL)
            return render_template("index.html", error=error)

        cache = cm.cache_check(youtube_id)

        if cache is not False:
            title, time_line, time_line_enemy, time_data, total_damage, debuff_value, past_status = cache
            if past_status % 100 // 10 == 0:
                debuff_dict, data_txt, data_url, total_damage = get_web_txt(
                    youtube_id, title, time_line, debuff_value, total_damage)

                return render_template("result.html",
                                       title=title,
                                       timeLine=time_line,
                                       timeLineEnemy=time_line_enemy,
                                       timeData=time_data,
                                       totalDamage=total_damage,
                                       debuffDict=debuff_dict,
                                       data_txt=data_txt,
                                       data_url=data_url)

            else:
                error = state.get_error_message(past_status)
                return render_template("index.html", error=error)

        if SERVER_ERROR_STATE:
            error = state.get_error_message(state.ERR_SERVICE_UNAVAILABLE)
            return render_template("index.html", error=error)

        # start download
        dl_queue_path = dl_queue_dir + str(youtube_id)
        dl_ongoing_path = dl_ongoing_dir + str(youtube_id)

        # 既にキューに登録されているか確認
        queued = os.path.exists(dl_queue_path)
        if not queued:  # 既にダウンロード待機中ではない場合、ダウンロード待機キューに登録
            cm.queue_append(dl_queue_path)
            # キューが回ってきたか確認し、来たらダウンロード実行
            while True:
                if not cm.is_path_exists(dl_ongoing_path) and cm.is_path_due(
                        dl_queue_path):
                    if cm.is_pending_download(15):  # check pending download
                        break

                timeout = cm.watchdog_download(youtube_id, 300)  # 5分間タイムアウト監視

                if timeout:
                    cm.clear_path(dl_queue_path)
                    error = "動画の解析待ちでタイムアウトが発生しました。再実行をお願いします。"
                    return render_template("index.html", error=error)

                tm.sleep(1)

        else:  # ダウンロード待機中の場合エラーメッセージ表示
            cm.clear_path(dl_queue_path)
            error = "同一の動画が解析中です。時間を置いて再実行をお願いします。"
            return render_template("index.html", error=error)

        path, title, length, thumbnail, url_result = al.search(youtube_id)
        cm.clear_path(dl_queue_path)

        if url_result % 100 // 10 == 2:
            error = state.get_error_message(url_result)
            cm.save_cache(youtube_id, title, False, False, False, False, False,
                          url_result)
            return render_template("index.html", error=error)

        session["path"] = path
        session["title"] = title
        session["youtube_id"] = youtube_id
        length = int(int(length) / 8) + 3

        return render_template("analyze.html",
                               title=title,
                               length=length,
                               thumbnail=thumbnail)

    elif request.method == "GET":
        if "v" in request.args:  # ?v=YoutubeID 形式のGETであればリザルト返却
            youtube_id = request.args.get("v")
            if re.fullmatch(r"^([a-zA-Z0-9_-]{11})$", youtube_id):
                cache = cm.cache_check(youtube_id)
                if cache is not False:
                    title, time_line, time_line_enemy, time_data, total_damage, debuff_value, past_status = cache
                    if past_status % 100 // 10 == 0:
                        debuff_dict, data_txt, data_url, total_damage = get_web_txt(
                            youtube_id, title, time_line, debuff_value,
                            total_damage)

                        return render_template("result.html",
                                               title=title,
                                               timeLine=time_line,
                                               timeLineEnemy=time_line_enemy,
                                               timeData=time_data,
                                               totalDamage=total_damage,
                                               debuffDict=debuff_dict,
                                               data_txt=data_txt,
                                               data_url=data_url)

                    else:
                        error = state.get_error_message(past_status)
                        return render_template("index.html", error=error)

                else:  # キャッシュが存在しない場合は解析
                    if SERVER_ERROR_STATE:
                        error = state.get_error_message(
                            state.ERR_SERVICE_UNAVAILABLE)
                        return render_template("index.html", error=error)

                    # start download
                    dl_queue_path = dl_queue_dir + str(youtube_id)
                    dl_ongoing_path = dl_ongoing_dir + str(youtube_id)

                    # 既にキューに登録されているか確認
                    queued = os.path.exists(dl_queue_path)
                    if not queued:  # 既にダウンロード待機中ではない場合、ダウンロード待機キューに登録
                        cm.queue_append(dl_queue_path)
                        # キューが回ってきたか確認し、来たらダウンロード実行
                        while True:
                            if not cm.is_path_exists(
                                    dl_ongoing_path) and cm.is_path_due(
                                        dl_queue_path):
                                if cm.is_pending_download(
                                        15):  # check pending download
                                    break

                            timeout = cm.watchdog_download(youtube_id,
                                                           300)  # 5分間タイムアウト監視

                            if timeout:
                                cm.clear_path(dl_queue_path)
                                error = "動画の解析待ちでタイムアウトが発生しました。再実行をお願いします。"
                                return render_template("index.html",
                                                       error=error)

                            tm.sleep(1)

                    else:  # ダウンロード待機中の場合エラーメッセージ表示
                        cm.clear_path(dl_queue_path)
                        error = "同一の動画が解析中です。時間を置いて再実行をお願いします。"
                        return render_template("index.html", error=error)

                    path, title, length, thumbnail, url_result = al.search(
                        youtube_id)
                    cm.clear_path(dl_queue_path)

                    if url_result % 100 // 10 == 2:
                        error = state.get_error_message(url_result)
                        cm.save_cache(youtube_id, title, False, False, False,
                                      False, False, url_result)
                        return render_template("index.html", error=error)

                    session["path"] = path
                    session["title"] = title
                    session["youtube_id"] = youtube_id
                    length = int(int(length) / 8) + 3

                    return render_template("analyze.html",
                                           title=title,
                                           length=length,
                                           thumbnail=thumbnail)

            else:  # prilog.jp/(YoutubeID)に該当しないリクエスト
                error = "不正なリクエストです"
                return render_template("index.html", error=error)

        else:
            path = session.get("path")
            session.pop("path", None)
            session.pop("title", None)
            session.pop("youtube_id", None)

            error = None
            if str(path).isdecimal():
                error = state.get_error_message(path)

            elif path is not None:
                cm.clear_path(path)

            return render_template("index.html", error=error)
Пример #8
0
def analyze_movie(movie_path):
    """analyze movie main

    check movie frames and find ub frame
    check frame: 0.34 sec (20 frames)

    Args
        movie_path (string): movie save path

    Returns
        ub_data (list): found ub data
        ub_data_enemy (list): found ub data with enemy ub
        time_data (list): spend time while analyze
        total_damage (string): total damage
        debuff_value (list): ub timing debuff values
        status (int): analyze status 200 (HD analyze) or 301 (SD analyze)


    """
    start_time = tm.time()
    video = cv2.VideoCapture(movie_path)

    frame_count = int(video.get(7))  # get total frame
    frame_rate = int(video.get(5))  # get frame rate

    frame_width = int(video.get(3))  # get frame width
    frame_height = int(video.get(4))  # get frame height

    try:
        video_type = FRAME_RESOLUTION.index((frame_width, frame_height))
    except ValueError:
        video.release()
        cm.clear_path(movie_path)

        return None, None, None, None, None, state.ERR_BAD_RESOLUTION

    model_init(video_type)
    roi_init(video_type)

    n = 0.34

    time_min = "1"
    time_sec10 = "3"
    time_sec1 = "0"

    menu_check = False

    min_roi = MIN_ROI
    tensec_roi = TEN_SEC_ROI
    onesec_roi = ONE_SEC_ROI
    ub_roi = UB_ROI
    score_roi = SCORE_ROI
    damage_data_roi = DAMAGE_DATA_ROI
    speed_roi = SPEED_ICON_ROI

    ub_data = []
    ub_data_enemy = []
    ub_data_value = []
    time_data = []
    characters_find = []

    tmp_damage = []
    total_damage = False

    cap_interval = int(frame_rate * n)
    past_time = 90
    time_count = 0
    find_id = -1
    find_count = 0

    if (frame_count / frame_rate) < 600:  # only check less than 10 min movie
        for i in range(frame_count):  # cycle check movie per frame
            ret = video.grab()
            if ret is False:
                break

            if i % cap_interval is 0:
                ret, original_frame = video.read()

                if ret is False:
                    break

                if video_type is RESOLUTION_16_9_SD:
                    original_frame = expand_frame(original_frame)

                work_frame = edit_frame(original_frame)

                if menu_check is False:
                    menu_check, menu_loc = analyze_menu_frame(work_frame, MENU_DATA, MENU_ROI)
                    if menu_check is True:
                        loc_diff = np.array(MENU_LOC) - np.array(menu_loc)
                        roi_diff = (loc_diff[0], loc_diff[1], loc_diff[0], loc_diff[1])
                        min_roi = np.array(MIN_ROI) - np.array(roi_diff)
                        tensec_roi = np.array(TEN_SEC_ROI) - np.array(roi_diff)
                        onesec_roi = np.array(ONE_SEC_ROI) - np.array(roi_diff)
                        ub_roi = np.array(UB_ROI) - np.array(roi_diff)
                        score_roi = np.array(SCORE_ROI) - np.array(roi_diff)
                        damage_data_roi = np.array(DAMAGE_DATA_ROI) - np.array(roi_diff)
                        speed_roi = np.array(SPEED_ICON_ROI) - np.array(roi_diff)

                        analyze_anna_icon_frame(work_frame, CHARACTER_ICON_ROI, characters_find)

                else:
                    if time_min is "1":
                        time_min = analyze_timer_frame(work_frame, min_roi, 2, time_min)

                    time_sec10 = analyze_timer_frame(work_frame, tensec_roi, 6, time_sec10)
                    time_sec1 = analyze_timer_frame(work_frame, onesec_roi, 10, time_sec1)

                    find_time = time_min + ":" + time_sec10 + time_sec1
                    now_time, is_same_time = time_check(time_min, time_sec10, time_sec1, past_time)

                    is_normal_speed = analyze_speed(original_frame, speed_roi)

                    if is_same_time:
                        #  count up if normal speed, neither, reset count
                        if is_normal_speed:
                            time_count += 1
                        else:
                            time_count = 0
                    else:
                        time_count = 0
                        past_time = now_time

                    if time_count >= 0:
                        # check friendly ub
                        ub_result, find_id, find_count = analyze_ub_frame(work_frame, ub_roi, time_min, time_sec10,
                                                                          time_sec1,
                                                                          ub_data, ub_data_enemy, ub_data_value,
                                                                          characters_find, find_id, find_count)

                        if ub_result:
                            # update count
                            time_count = update_count(frame_rate, find_id, cap_interval)

                        elif is_normal_speed:
                            # check enemy ub
                            analyze_enemy_ub(time_count, work_frame, find_time, ub_data_enemy)

                    # check score existence
                    ret = analyze_score_frame(work_frame, SCORE_DATA, score_roi)

                    if ret is True:
                        # analyze total damage
                        ret = analyze_damage_frame(original_frame, damage_data_roi, tmp_damage)

                        if ret is True:
                            total_damage = "".join(tmp_damage)

                        break

    video.release()
    cm.clear_path(movie_path)

    # post-processing to timeline
    if len(ub_data_enemy) != 0 and ENEMY_UB in ub_data_enemy[-1]:
        ub_data_enemy.pop()

    debuff_value = ac.make_ub_value_list(ub_data_value, characters_find)

    time_result = tm.time() - start_time
    time_data.append("動画時間 : {:.3f}".format(frame_count / frame_rate) + "  sec")
    time_data.append("処理時間 : {:.3f}".format(time_result) + "  sec")

    status = get_analyze_status(ub_data, video_type)

    if status is not state.DONE:
        ub_data_enemy = False

    return ub_data, ub_data_enemy, time_data, total_damage, debuff_value, status
Пример #9
0
def search(youtube_id):
    """get movie from youtube

    get movie from YouTube iTag 22 (720p / mp4) or iTag 18 (360p / mp4)

    Args:
        youtube_id (str): user input youtube_id

    Returns:
        movie_path (str): movie save path
        movie_title (str): movie title
        movie_length (str): movie length
        movie_thumbnail (str): movie thumbnail url
        status (str): error status while get movie


    """
    # add dl ongoing queue
    dl_ongoing_path = ap.dl_ongoing_dir + str(youtube_id)
    cm.queue_append(dl_ongoing_path)

    youtube_url = "https://www.youtube.com/watch?v=" + youtube_id

    try:
        # add dl pending queue
        dl_pending_path = ap.dl_pending_dir + "pending"
        cm.queue_append(dl_pending_path)
        yt = YouTube(youtube_url)

    except KeyError as e:
        # cant get movie by status
        ret = state.ERR_PERM_UNEXPECTED
        error = e.args[0]
        if error == "cipher":
            ret = state.ERR_COPYRIGHTED_CONTENT
        elif error == "adaptiveFormats":
            ret = state.TMP_CANT_GET_HD
        elif error == "formats":
            ret = state.ERR_UNAVAILABLE_CONTENT

        cm.clear_path(dl_ongoing_path)
        return None, None, None, None, ret

    except exceptions.RegexMatchError:
        # cant get movie by private or deleted
        cm.clear_path(dl_ongoing_path)
        return None, None, None, None, state.TMP_CANT_GET_HD

    except:
        # cant get movie by other reason
        cm.clear_path(dl_ongoing_path)
        return None, None, None, None, state.TMP_CANT_GET_HD

    movie_thumbnail = yt.thumbnail_url
    movie_length = yt.length
    if int(movie_length) > MOVIE_LENGTH_MAX:
        cm.clear_path(dl_ongoing_path)
        return None, None, None, None, state.ERR_BAD_LENGTH

    status = state.DONE
    stream = yt.streams.get_by_itag(22)
    if stream is None:
        status = state.TMP_DONE_IN_SD
        stream = yt.streams.get_by_itag(18)
        if stream is None:
            cm.clear_path(dl_ongoing_path)
            return None, None, None, None, state.ERR_BAD_RESOLUTION

    movie_title = stream.title
    movie_name = tm.time()
    movie_path = stream.download(ap.stream_dir, str(movie_name))

    cm.clear_path(dl_ongoing_path)

    return movie_path, movie_title, movie_length, movie_thumbnail, status
Пример #10
0
def analyze_movie(movie_path):
    """analyze movie main

    check movie frames and find ub frame
    check frame: 0.34 sec (20 frames)

    Args
        movie_path (string): movie save path

    Returns
        ub_data (list): found ub data
        time_data (list): spend time while analyze
        total_damage (string): total damage
        debuff_value (list): ub timing debuff values
        status (int): analyze status 200 (HD analyze) or 301 (SD analyze)


    """
    start_time = tm.time()
    video = cv2.VideoCapture(movie_path)

    frame_count = int(video.get(7))  # get total frame
    frame_rate = int(video.get(5))  # get frame rate

    frame_width = int(video.get(3))  # get frame width
    frame_height = int(video.get(4))  # get frame height

    try:
        video_type = FRAME_RESOLUTION.index((frame_width, frame_height))
    except ValueError:
        video.release()
        cm.clear_path(movie_path)

        return None, None, None, None, el.ERR_BAD_RESOLUTION

    if video_type is RESOLUTION_16_9_SD:
        status = el.TMP_DONE_IN_SD
    else:
        status = el.DONE

    model_init(video_type)
    roi_init(video_type)

    n = 0.34
    ub_interval = 0

    time_min = "1"
    time_sec10 = "3"
    time_sec1 = "0"

    menu_check = False

    min_roi = MIN_ROI
    tensec_roi = TEN_SEC_ROI
    onesec_roi = ONE_SEC_ROI
    ub_roi = UB_ROI
    score_roi = SCORE_ROI
    damage_data_roi = DAMAGE_DATA_ROI

    ub_data = []
    ub_data_value = []
    time_data = []
    characters_find = []

    tmp_damage = []
    total_damage = False

    cap_interval = int(frame_rate * n)
    skip_frame = 5 * cap_interval

    if (frame_count / frame_rate) < 600:  # only check less than 10 min movie
        for i in range(frame_count):  # cycle check movie per frame
            ret = video.grab()
            if ret is False:
                break

            if i % cap_interval is 0:
                if ((i - ub_interval) > skip_frame) or (ub_interval == 0):
                    ret, original_frame = video.read()

                    if ret is False:
                        break

                    if video_type is RESOLUTION_16_9_SD:
                        original_frame = expand_frame(original_frame)

                    work_frame = edit_frame(original_frame)

                    if menu_check is False:
                        menu_check, menu_loc = analyze_menu_frame(
                            work_frame, MENU_DATA, MENU_ROI)
                        if menu_check is True:
                            loc_diff = np.array(MENU_LOC) - np.array(menu_loc)
                            roi_diff = (loc_diff[0], loc_diff[1], loc_diff[0],
                                        loc_diff[1])
                            min_roi = np.array(MIN_ROI) - np.array(roi_diff)
                            tensec_roi = np.array(TEN_SEC_ROI) - np.array(
                                roi_diff)
                            onesec_roi = np.array(ONE_SEC_ROI) - np.array(
                                roi_diff)
                            ub_roi = np.array(UB_ROI) - np.array(roi_diff)
                            score_roi = np.array(SCORE_ROI) - np.array(
                                roi_diff)
                            damage_data_roi = np.array(
                                DAMAGE_DATA_ROI) - np.array(roi_diff)

                            analyze_anna_icon_frame(work_frame,
                                                    CHARACTER_ICON_ROI,
                                                    characters_find)

                    else:
                        if time_min is "1":
                            time_min = analyze_timer_frame(
                                work_frame, min_roi, 2, time_min)

                        time_sec10 = analyze_timer_frame(
                            work_frame, tensec_roi, 6, time_sec10)
                        time_sec1 = analyze_timer_frame(
                            work_frame, onesec_roi, 10, time_sec1)

                        ub_result = analyze_ub_frame(work_frame, ub_roi,
                                                     time_min, time_sec10,
                                                     time_sec1, ub_data,
                                                     ub_data_value,
                                                     characters_find)

                        if ub_result is FOUND:
                            ub_interval = i

                        # check score existence
                        ret = analyze_score_frame(work_frame, SCORE_DATA,
                                                  score_roi)

                        if ret is True:
                            # analyze total damage
                            ret = analyze_damage_frame(original_frame,
                                                       damage_data_roi,
                                                       tmp_damage)

                            if ret is True:
                                total_damage = "".join(tmp_damage)

                            break

    video.release()
    cm.clear_path(movie_path)

    # post-processing to timeline
    debuff_value = ac.make_ub_value_list(ub_data_value, characters_find)

    time_result = tm.time() - start_time
    time_data.append("動画時間 : {:.3f}".format(frame_count / frame_rate) +
                     "  sec")
    time_data.append("処理時間 : {:.3f}".format(time_result) + "  sec")

    return ub_data, time_data, total_damage, debuff_value, status