Converting `for file in` to `find` so that my script can apply recursively

With POSIX find:

find . \( -name '*.mkv' -o -name '*avi' -o -name '*mp4' -o -name '*flv' -o \
          -name '*ogg' -o -name '*mov' \) -exec sh -c '
  for file do
    target="${file%.*}.mkv"
    echo ffmpeg -i "$file" "$target"
  done' sh {} +

Replace echo with whatever command you want to use.

If you have GNU find or BSD find, you can use -regex:

find . -regex '.*\.\(mkv\|avi\|mp4\|flv\|ogg\|mov\)'

You've got this code:

for file in *.mkv *avi *mp4 *flv *ogg *mov; do
target="${file%.*}.mkv"
    ffmpeg -i "$file" "$target" && rm -rf "$file"
done

which runs in the current directory. To turn it into a recursive process you have a couple of choices. The easiest (IMO) is to use find as you suggested. The syntax for find is very "un-UNIX-like" but the principle here is that each argument can be applied with AND or OR conditions. Here, we're going to say "If this-filename matches OR that-filename matches Then print-it". The filename patterns are quoted so that the shell can't get hold of them (remember that the shell is responsible for expanding all unquoted patterns, so if you had an unquoted pattern of *.mp4 and you had janeeyre.mp4 in your current directory, the shell would replace *.mp4 with the match, and find would see -name janeeyre.mp4 instead of your desired -name *.mp4; it gets worse if *.mp4 matches multiple names...). The brackets are prefixed with \ also to keep the shell from trying to action them as subshell markers (we could quote the brackets instead, if preferred: '(').

find . \( -name '*.mkv' -o -name '*avi' -o -name '*mp4' -o -name '*flv' -o -name '*ogg' -o -name '*mov' \) -print

The output of this needs to be fed into the input of a while loop that processes each file in turn:

while IFS= read file    ## IFS= prevents "read" stripping whitespace
do
    target="${file%.*}.mkv"
    ffmpeg -i "$file" "$target" && rm -rf "$file"
done

Now all that's left is to join the two parts together with a pipe | so that the output of the find becomes the input of the while loop.

While you're testing this code I'd recommend you prefix both ffmpeg and rm with echo so you can see what would be executed - and with what paths.

Here is the final result, including the echo statements I recommend for testing:

find . \( -name '*.mkv' -o -name '*avi' -o -name '*mp4' -o -name '*flv' -o -name '*ogg' -o -name '*mov' \) -print |
    while IFS= read file    ## IFS= prevents "read" stripping whitespace
        do
            target="${file%.*}.mkv"
            echo ffmpeg -i "$file" "$target" && echo rm -rf "$file"
        done

Example snippet without piping (assumes you are giving the path as argument):

#!/bin/bash

backup_dir=/backup/

OIFS="$IFS"
IFS=$'\n'

files="$(find "$1" -type f -name '*.mkv' -or -name '*.avi' -or -name '*.mp4' -or -name '*.ogg' -or -name '*.mov' -or -name '*.flv')"

for f in $files; do
    # get path
    d="${f%/*}"
    # get filename
    b="$(basename "$f")"
    ttarget="${b%.*}.mkv"

    # this is your final target
    target="$d/$ttarget"
    echo $target
    # mv $f "$backup_dir" 
done

IFS="$OIFS"

The shell reads the IFS variable, which is set to (space, tab, newline) by default. Then it looks at each character in the output of find. So if it finds space it thinks it is end of the filename (file containing spaces for example "Sin City.avi" ill be treated as two files "Sin" and "City.avi"). So with IFS=$'\n' we are telling to split the input on newlines. And finally we restore old (default) IFS which is saved in $OIFS variable.
Or as suggested in comments may be better approach could be:

#!/bin/bash

backup_dir=/backup/

find "$1" -type f \( -name '*.mkv' -or -name '*.avi' -or -name '*.mp4' -or -name '*.ogg' -or -name '*.mov' -or -name '*.flv' \) -print0 | while IFS= read -r -d '' f
do
    # get path
    d="${f%/*}"
    # get filename
    b="$(basename "$f")"
    ttarget="${b%.*}.mkv"

    # this is your final target
    target="$d/$ttarget"
    echo $target
    # mv $f "$backup_dir"
done