To clarify, the convolution operation in general can be used to reduce dimensionality. But since we want to assure that the new representation contains the information we need, its useful to discuss the ways we can stride over the data.
Here’s an example I made to show the two methods I’ve mentioned:

import torch
import torch.nn as nn

def stride_over_channels(x):
    # Since our timesteps is in our "channels" position, we slowly
    # reduce it down to 1.
    # This is striding over our channels
    c1 = nn.Conv3d(in_channels=8, out_channels=4, kernel_size=3, padding=1)
    c2 = nn.Conv3d(in_channels=4, out_channels=1, kernel_size=3, padding=1)

    out1 = c1(x)            # batch-size x 4 x channels x height x width
    out2 = c2(out1)         # batch-size x 1 x channels x height x width
    out3 = out2.squeeze(1)  # batch-size x channels x height x width

    return out3

def stride_over_time(x):
    # Swap the dimensions to be batch-size x channels x timesteps x height x width
    # This causes us to stride over time
    x = x.permute((0, 2, 1, 3, 4))

    # Slowly reduce our channels down to 1
    c1 = nn.Conv3d(in_channels=16, out_channels=8, kernel_size=3, padding=1)
    c2 = nn.Conv3d(in_channels=8, out_channels=1, kernel_size=3, padding=1)

    out1 = c1(x)            # batch-size x 8 x timesteps x height x width
    out2 = c2(out1)         # batch-size x 1 x timesteps x height x width
    out3 = out2.squeeze(1)  # batch-size x timesteps x height x width

    return out3

def stride_over_time_2(x):
    # Swap the dimensions to be batch-size x channels x timesteps x height x width
    x = x.permute((0, 2, 1, 3, 4))

    # We can be even fancier and and build our channels up while
    # reducing our temporal dimension. This however requires more convolution
    # and thus more parameters
    c1 = nn.Conv3d(in_channels=16, out_channels=32, kernel_size=3, padding=(0, 1, 1))
    c2 = nn.Conv3d(in_channels=32, out_channels=64, kernel_size=3, padding=(0, 1, 1))
    c3 = nn.Conv3d(in_channels=64, out_channels=128, kernel_size=3, padding=(0, 1, 1))

    out1 = c1(x)            # batch-size x 32  x 6 x height x width
    out2 = c2(out1)         # batch-size x 64  x 4 x height x width
    out3 = c3(out2)         # batch-size x 128 x 2 x height x width

    # 2 isn't a nice size to perform a convolution on
    # So lets just collapse it at this point
    out4 = out3.view(-1, 256, 64, 64)

    return out4


# x is batch-size x timesteps x channels x height x width
x = torch.randn((4, 8, 16, 64, 64))

y1 = stride_over_channels(x)
y2 = stride_over_time(x)
y3 = stride_over_time_2(x)

print(y1.shape)  # 4 x 16  x 64 x 64
print(y2.shape)  # 4 x 8   x 64 x 64
print(y3.shape)  # 4 x 256 x 64 x 64

This is was a suggestion based off my personal experienced. I’ve worked with temporal-spatial data so the question of “how do we perform convolutions on this data?” has come up. I hope my example code clear things up for you. Let me know if anything is still confusing.