How to remove the replace the product image by video on shop page conditionally

It loads twice, I believed it is due to another hook exists also. You might need to remove another unwanted hook. And actually you don’t have to run the action woocommerce_before_shop_loop_item_title inside another hook.

Example for class to remove action

If you want to place a remove_action in a class, there are different ways to do so. The following example illustrate 2 ways.
The following class is proved to work for either putting in default storefront theme’s functions.php or in a plugin provided that the site is running without interference of other additional plugins.

class example {
    public function __construct() {
        // option1: place here will work
        remove_action( 'woocommerce_before_shop_loop_item_title', 'woocommerce_template_loop_product_thumbnail', 10 );

        // wrong demonstration: will not work because original call is not a class, it is not necessary to use class method to remove
        // remove_action( 'woocommerce_before_shop_loop_item_title', array( $this 'woocommerce_template_loop_product_thumbnail' ), 10 );

        add_action( 'init', array( $this, 'init' ) );
    }

    // option2: if you want to ***group different actions*** together, it also works.
    public function init() {
        // place here also work
        // remove_action( 'woocommerce_before_shop_loop_item_title', 'woocommerce_template_loop_product_thumbnail', 10 );

        // other remove actions or actions
    } 
}

new example();

individual action

If you move the action out of the init hook and try again and remove unwanted hook.
If you want to add it into your plugin without the init hook, just change in this way.

// your ' show_video' is already doing the job `show_video_if_set_else_image`
// so you might want to change this function name too
remove_action( 'woocommerce_before_shop_loop_item_title', 'woocommerce_template_loop_product_thumbnail', 10 );
add_action('woocommerce_before_shop_loop_item_title', array($this, 'show_video' ) );

    function show_video(){
        $linkk = get_post_meta(get_the_ID(), 'YT_video_link', true);
        $linkk = substr($linkk, -11);
        if($linkk != ''){
            echo 'show video';
            // if you put remove_action, it will not work as expected because the remove_action is run after add_action, so before it removes, it run already.

            ?>
            <div class="woocommerce-product-gallery">

                <iframe width="420" height="315"
                src="http://www.youtube.com/embed/<?php echo $linkk; ?>" allowfullscreen>
                </iframe>
            </div>
            <?php

        }else{    # in this part I don't know what to do
            echo 'show image';
            ?>
            <img src="<?php echo get_the_post_thumbnail_url( get_the_ID() ); ?>" />
            <?php
        }
    }

about priority

If you want to change the priority of the title hook, you just need to adjust the priority sooner or later eg
add_action( 'woocommerce_before_shop_loop_item_title', 'some_function', 50 );

WordPress hook system is an event based system. It follow a series of events called filters or actions.
Normally, filters let you override a value while action let you do additionally jobs. So it run by following priority and order.
For actions, it do job at specific time. So, one job at a time.
You don’t need to add a job using another job most of the time unless there is a special reason. Because action itself exists independently at different points defined by do_action().

Even you add in init hook, the queue for woocommerce_before_shop_loop_item_title is still running at do_action( 'woocommerce_before_shop_loop_item_title'), it will not run earlier. The priority for changing the hook is for the same hook, because there might be some other actions running that you want to override. You may then adjust your hook to run later to ensure your override work.

about double running

There is probably existing woocommerce_before_shop_loop_item_title action doing similar things. So if it output twice because you output once and original action output once.

If you want to remove existing action(s). You just need to run:
(the following is Woocommerce default action)

remove_action( 'woocommerce_before_shop_loop_item_title', 'woocommerce_template_loop_product_thumbnail', 10 );

You may refer to remove_action()

Hook name, function name and priority must be same as original in order to remove it so you may refer to that source code or find the code in the folder for accurate information.