I checked your query and there’s a lot of junk in there. You define meta keys 2x. Once as meta_key and once as meta_query. Only keep the query, it has more options.
Second, the tax query is all wrong. The parameters for a tax query are not the same as a meta query. You need taxonomy, field, terms and possible compare. I don’t see a reason to use a tax query, based on your info, so I removed it in my example.
I am a fan of storing dates/times as a unix timestamp. Is a lot easier to compare and order than a date string. By looking at your today string, I assume the rest is in that format as well, so I will use that for the example.
I wrote the code below by heart since I had no events to work with (with that meta key), but I think you’ll get most of the desired result and if not, maybe tweak it a little.
$today = date( 'Y/m/d' );
$args = array(
'post_type' => 'event',
'posts_per_page' => 10,
'order' => 'ASC',
'meta_query' => array(
// get posts which have an end_datetime which is bigger than or equal to $today (and thus hide the ones which have ended before today)
'end_clause' => array(
'key' => 'end_datetime',
'value' => $today,
'compare' => '>=',
'type' => 'DATE'
)
),
'orderby' => array( 'end_clause' => 'DESC' ),
);
$query = new WP_Query( $args );
if ( $query->have_posts() ) {
while( $query->have_posts() ) {
$query->the_post();
the_title();
// check if start_datetime is not empty
if ( ! empty( get_post_meta( get_the_ID(), 'start_datetime', 1 ) ) ) {
// make unix timestamp of start_datetime
$start_datetime = strtotime( date( 'U', get_post_meta( get_the_ID(), 'start_datetime', 1 ) ) );
// make unix timestamp of now
$now = date( 'U', current_time( 'timestamp' ) );
// if (start_time - now) is smaller than 7200 seconds
if ( ( $start_datetime - $now ) < 2 * HOUR_IN_SECONDS ) {
echo '<p>LIVE</p>';
}
}
}
}
Let me know if this helps.