Automatically convert videos in Powerpoint file (pptx) to a different format

I have been trying to convert a lot of embedded videos in pptx files to a different format lately due to compatibility issues on some systems, but have not found an easy and fast way – so I wrote this bash script.

The goal was to have a pptx with videos that can be played using Powerpoint 2010 or later on Windows as well as OS X without plugins. That seems to only be the case for MPG videos (mpeg1video codec).

To convert videos in a presentation

  1. make sure that ffmpeg and a zip/unzip application is installed (ffmpeg can easily be replaced by avconv, but avconv somehow could not convert some files that were no problem for ffmpeg during my tests)
  2. download the bash file and make it executable
  3. edit the options at the beginning of the file, if you want to (mainly video output format and bitrate)
  4. Change to the directory with the pptx file(s) and start the conversion with /path/to/pptx_video_convert.sh myPresentation.pptx
  5. Check if everything worked by looking at myPresentation_converted.pptx  or the logs

I’m not sure whether this will work with all pptx files. It assumes that videos are in the folder ppt/media , have the names media[0-9]*.EXT  (EXT just being any extension) and are only directly referenced by files in ppt/slides/_rels .

The script does the following:

  1. unzip pptx
  2. transcode video files using ffmpeg
  3. update file references in ppt/slides/_rels
  4. add MIME type to [Content_Types].xml  (especially this might go wrong)
  5. Rezip contents
#!/bin/bash

THREADS=4  # number of threads for ffmpeg
OUTPUT_VIDEO_FORMAT="mpeg1video" # -c:v parameter for ffmpeg
OUTPUT_VIDEO_BITRATE="4000k" # in bit/s
OUTPUT_VIDEO_FRAMERATE="25" # framerate in fps
OUTPUT_FILEEXTENSION="mpg" # note that this will also be added as MIME type to [Content_Types].xml in the format video/ext!
REMOVE_OLD_FILES=1 # remove old pptx files after conversion


if [ $# -ne 1 ]; then
  echo 1>&2 "Usage: $0 PPTX_FILE"
  exit
fi


FILE=$1
FOLDER="$FILE""_DIR"

mkdir -p "/tmp/pptx_conv/$FILE" # for log files

mkdir "$FOLDER"
cd "$FOLDER"

echo "--------------------"
echo "Unzipping <$FILE>..."
unzip ../"$FILE" > /dev/null

# convert video files
for OLD_NAME in ppt/media/media*.*
do
    # cancel early if no video files are detected
    if [ ! -e "$OLD_NAME" ]
    then
        echo "No video files detected"
        cd ..
        rm -rf "$FOLDER"
    	echo "Cleaned up. Did not create converted file, because there was nothing to convert."
        echo "--------------------"
        exit
    fi

    BASE_NAME=$(echo $OLD_NAME | cut -d "." -f1)
    NEW_NAME=$BASE_NAME"."$OUTPUT_FILEEXTENSION
    FFMPEG_OUTPUT=$(ffmpeg -threads $THREADS -i $OLD_NAME -b:v $OUTPUT_VIDEO_BITRATE -c:v $OUTPUT_VIDEO_FORMAT -r $OUTPUT_VIDEO_FRAMERATE $NEW_NAME 2>&1)
    RETURN_VALUE=$? # whether ffmpeg command worked

    if [ $RETURN_VALUE -eq 0 ]
    then
        echo "Successfully converted $OLD_NAME to $NEW_NAME"
    else
        echo "<!> Failed to convert $OLD_NAME to $NEW_NAME"
    fi

    LOG_FILE="/tmp/pptx_conv/"$FILE"/$RANDOM"
    echo "$FFMPEG_OUTPUT" > "$LOG_FILE"
    echo "Saved ffmpeg output to <$LOG_FILE>"

    rm $OLD_NAME
done


# change references to video files
for SLIDE in ppt/slides/_rels/*.rels
do
    sed -ri 's/Target="..\/media\/(media[0-9]*)\.[^"]*"/Target="..\/media\/\1\.mpg"/g' $SLIDE
done

# Add mime type to [Content_Types].xml
MIME_FILE="[Content_Types].xml"
MIME_LINE="<Default Extension=\"$OUTPUT_FILEEXTENSION\" ContentType=\"video\/$OUTPUT_FILEEXTENSION\"\/>"

PNG_MIME_LINE="<Default Extension=\"png\" ContentType=\"image\/png\"\/>" # add the new mime line behind this

# check whether line is already there
MATCHES=$(cat $MIME_FILE | grep -c $OUTPUT_FILEEXTENSION)
if [ ! $MATCHES -gt 0 ]
then
    # no match, so add the line somewhere
    sed -i "s/$PNG_MIME_LINE/$PNG_MIME_LINE $MIME_LINE/g" $MIME_FILE
fi

BASE_NAME=$(echo "$FILE" | cut -d "." -f1)
NEW_NAME="$BASE_NAME""_converted.pptx"
echo "Zipping up <$NEW_NAME>..."
zip -r ../"$NEW_NAME" * > /dev/null

# cleanup
cd ..
rm -rf "$FOLDER"

if [ $REMOVE_OLD_FILES -eq 1 ];
then
    rm "$FILE"
fi

echo "--------------------"

Leave a Reply

Your email address will not be published. Required fields are marked *