Video Conversion for Sansa Fuze

Share your own howto's etc. Not for support questions!

Video Conversion for Sansa Fuze

Postby julian67 » 2010-02-27 12:27

I know there are a few people here who have one of these so this might be some good news:

Fuze needs a very specific video, audio and container format or it won't play the video, specifically:

Video:
Frame rate: 20 fps
(Fourcc: DX50)
Width x Height: 224 x 176
Scan Type: Progressive
Keyframe interval: 15 frames
Video Bitrate: 500-700 Kbps

Audio: MP3, 2 channel, CBR, (128 kbps), little endian

Avi Container:
ODML index, index point every 4000 frames
Audio alignment: align on interleaves
Interleave interval: every 2 video frames

stuff (in brackets) may be optional, not sure.

The problematic part has been to have an ODML index with specific settings, and to have the audio interleaving set to a specific interval. Mencoder and other converters either write ODML index or they don't, there's no way to fine tune this, or to force the audio to interleave every 2 video frames. People have been left with the choice of either using the Windows platform Sansa Media Converter (which is proprietary,slow, unstable, unreliable, doesn't run in wine, and is generally horrible) or using mencoder and then some Win32 freeware in wine which produces a video with seeking problems and poor A/V sync. Until now!

Some clever person has written fuzemux

It's a tiny piece of C code. Download, unpack, cd into the directory, and build the executable with
Code: Select all
gcc -std=c99 -O2 fuzemux.c riff.c -o fuzemux


Put the resulting fuzemux in your path i.e. /usr/local/bin or ~/bin if you use it, and make it executable.

You can now use mencoder to convert your video and run the result through fuzemux. It will then play fine on the Fuze with proper audio sync and seeking. Sample script:

Code: Select all
#!/bin/bash
# script name mensansa

for MOVIE in "$@" ; do

# Get movie name and strip extension - allow spaces dots etc
VIDOUT=$(basename "$MOVIE" |sed 's/\(.*\)\..*/\1/')

# Get original directory name of movie
DIRNAME=$(dirname "$MOVIE")

# Set output directory & name for converted movie
DEST="$DIRNAME"/"$VIDOUT"_fuze.avi

mencoder "$MOVIE" \
-srate 44100 -af resample=44100:0:1,format=s16le \
-oac mp3lame -lameopts cbr:br=128 \
-ovc lavc -lavcopts vcodec=mpeg4:vqscale=3:vmax_b_frames=0:keyint=15 \
-ofps 20 -noskiplimit -vf pp=li,expand=:::::224/176,scale=224:176 \
-ffourcc DX50 \
-o "$MOVIE"_premux.avi \
&& fuzemux "$MOVIE"_premux.avi "$DEST" \
&& rm "$MOVIE"_premux.avi
done


Usage:
Code: Select all
$ mensansa [video1 video2 video3....]


It will save the movie as movie_fuze.avi in the same directory as the original. The extra muxing step is pretty much instantaneous.

edit: if you want to save the converted movies to some other place such as a dedicated directory or the player itself then just change
DIRNAME=$(dirname "$MOVIE")
to
DIRNAME="/your/preferred/path/"

Another edit!

The Sansa Fuze can show thumbnails of the movies if the movie is accompanied by a .thm file. Sansa's .thm is actually just a jpg 224x176 with a silly extension. Anyway as long as you have ffmpegthumbnailer and imagemagick installed this can all be done at the same time as the movie conversion. ffmpegthumbnailer creates .png files, these need converting to jpg, and then the .png is removed:

edit: corrected script:
edit: another correction (change .thm to _fuze.thm)

Code: Select all
#!/bin/bash
for MOVIE in "$@" ; do
# Get movie name and strip extension - allow spaces dots etc
VIDOUT=$(basename "$MOVIE" |sed 's/\(.*\)\..*/\1/')
# Get original directory name of movie
DIRNAME=$(dirname "$MOVIE")
DEST="$DIRNAME"/"$VIDOUT"
ffmpegthumbnailer -s 224 -i "$MOVIE" -o THUM.png
convert THUM.png THUM.jpg
rm THUM.png
mv THUM.jpg "$DEST"_fuze.thm
mencoder "$MOVIE" \
-srate 44100 -af resample=44100:0:1,format=s16le \
-oac mp3lame -lameopts cbr:br=128 \
-ovc lavc -lavcopts vcodec=mpeg4:vbitrate=600:vqscale=3:vmax_b_frames=0:keyint=15:threads=2 \
-ofps 20 -noskiplimit -vf pp=li,expand=:::::224/176,scale=224:176 \
-ffourcc DX50 \
-o "$MOVIE"_premux.avi \
&& fuzemux "$MOVIE"_premux.avi "$DEST"_fuze.avi \
&& rm "$MOVIE"_premux.avi
done


As before if you want to save the converted movies and thumbs to some other place such as a dedicated directory or the player itself then just change
DIRNAME=$(dirname "$MOVIE")
to
DIRNAME="/your/preferred/path/"
Wisdom from my inbox: "do not mock at your pottenocy"
User avatar
julian67
 
Posts: 4648
Joined: 2007-04-06 14:39
Location: Just hanging around

Re: Video Conversion for Sansa Fuze

Postby KeithHedger » 2010-03-02 21:00

BRILLIANT!!!

I've had a sansa fuze for a couple of months (I'm quite impressed with it) and for the first few weeks I tried all sorts of things to encode some videos for it but no joy, I don't have windows installed on my machine so I couldn't use the sansa software as it doesn't run under wine, so I had resigned myself to no videos, but as I bought the fuze primarily to play music I wasn't too worried but it did niggle at me, but this software and scripts worked perfectly first time, well done for the scripts ( did you write the fuzemux as well ? if so another well done )

You might want to post a link to this post in some other forums as I'm sure a LOT of people will be pleased for this.

:) :) :) :) :)
In /dev/null no one can hear the kernel panic
User avatar
KeithHedger
 
Posts: 17
Joined: 2009-12-07 19:55
Location: Devon, U.K.

Re: Video Conversion for Sansa Fuze

Postby julian67 » 2010-03-03 02:16

Definitely not me who wrote fuzemux! On a good day I can write simple but clumsy bashscripts. C is way over my head.

I found fuzemux when browsing the Sansa Fuze forum http://forums.sandisk.com/sansa/board/message?board.id=sansafuse&thread.id=31437&view=by_date_ascending&page=24

It was only written and released last week but already people are integrating it into conversion applications, so I guess if GNU/Linux using Fuze owners need it they'll find it with the help of the almighty Google.
Wisdom from my inbox: "do not mock at your pottenocy"
User avatar
julian67
 
Posts: 4648
Joined: 2007-04-06 14:39
Location: Just hanging around

Re: Video Conversion for Sansa Fuze

Postby KeithHedger » 2010-03-16 17:06

ffmpegthumbnailer and convert is not necessary to generate the thumbnail try replacing
Code: Select all
    ffmpegthumbnailer -s 224 -i "$MOVIE" -o THUM.png
    convert THUM.png THUM.jpg
    rm THUM.png
    mv THUM.jpg "$DEST"_fuze.thm


with
Code: Select all
ffmpeg -i "$MOVIE" -t 1 -ss 5  -f image2 "THUM.jpg" 0</dev/null
mv THUM.jpg "$DEST"_fuze.thm


(ffmpegthumbnailer doesn't seem to be in the lenny repos)
In /dev/null no one can hear the kernel panic
User avatar
KeithHedger
 
Posts: 17
Joined: 2009-12-07 19:55
Location: Devon, U.K.

Re: Video Conversion for Sansa Fuze

Postby julian67 » 2010-03-16 17:20

Thanks for that, I hadn't realised ffmpeg could do snapshots.
Wisdom from my inbox: "do not mock at your pottenocy"
User avatar
julian67
 
Posts: 4648
Joined: 2007-04-06 14:39
Location: Just hanging around

Re: Video Conversion for Sansa Fuze

Postby julian67 » 2010-03-26 23:35

The image has to be resized to 224xheight so

Code: Select all
ffmpeg -i "$MOVIE" -t 1 -ss 60  -f image2 "THUM.jpg" 0</dev/null
convert -resize 224 THUM.jpg "$DEST"_fuze.thm


is better.

I changed the start value from 5 to 60 to avoid getting a thumbnail of the studio/distributor logo.

There is a new version of fuzemux with some fixes and now deb packages for both 32-bit and 64-bit are available. http://code.google.com/p/video4fuze/downloads/list

Here is a script with the above changes and also automatic cropping (removes black borders and makes sure the dimensions are divisible by 16, it doesn't change aspect ratio or do anything nasty)

Code: Select all
#!/bin/bash
function cropdetect ()
{
   CROP="1"
   TOTAL_LOOPS="10"

   A=0
   while [ "$A" -lt "$TOTAL_LOOPS" ] ; do
   A="$(( $A + 1 ))"
   SKIP_SECS="$(( 60 * $A ))"

   mplayer "$MOVIE" -ss $SKIP_SECS \
   -frames 20 -vo md5sum -nosound -nocache \
   -vf cropdetect=20:16 2>&1 > mplayer.log < /dev/null

   CROP[$A]=`awk -F 'crop=' '/crop/ {print $2}' < mplayer.log |\
   awk -F ')' '{print $1}' | tail -n 1`

done
   rm md5sums mplayer.log


   B=0
   while [ "$B" -lt "$TOTAL_LOOPS" ] ; do
   B="$(( $B + 1 ))"

   C=0
   while [ "$C" -lt "$TOTAL_LOOPS" ] ; do
   C="$(( $C + 1 ))"
 
if [ "${CROP[$B]}" == "${CROP[$C]}" ] ; then
   COUNT_CROP[$B]="$(( ${COUNT_CROP[$B]} + 1 ))"
fi
done 
done

   HIGHEST_COUNT=0

   D=0
   while [ "$D" -lt "$TOTAL_LOOPS" ] ; do
   D="$(( $D + 1 ))"

if [ "${COUNT_CROP[$D]}" -gt "$HIGHEST_COUNT" ] ; then
   HIGHEST_COUNT="${COUNT_CROP[$D]}"
   GREATEST="$D"
fi
done

   CROP="crop=${CROP[$GREATEST]}"
   echo -e "$CROP"

}

for MOVIE in "$@" ; do
# Get movie name and strip extension - allow spaces dots etc
VIDOUT=$(basename "$MOVIE" |sed 's/\(.*\)\..*/\1/')
# Get original directory name of movie
DIRNAME=$(dirname "$MOVIE")
DEST="$DIRNAME"/"$VIDOUT"
CROP="crop=$(cropdetect| awk -F 'crop=' '/crop/ {print $2}')"

ffmpeg -i "$MOVIE" -t 1 -ss 60  -f image2 "THUM.jpg" 0</dev/null
convert -resize 224 THUM.jpg "$DEST"_fuze.thm

mencoder "$MOVIE" \
-srate 44100 -af resample=44100:0:1,format=s16le \
-oac mp3lame -lameopts cbr:br=128 \
-ovc lavc -lavcopts vcodec=mpeg4:vbitrate=600:vqscale=3:vmax_b_frames=0:keyint=15:threads=2 \
-ofps 20 -noskiplimit -vf $CROP,pp=li,expand=:::::224/176,scale=224:176 \
-ffourcc DX50 \
-o "$MOVIE"_premux.avi \
&& fuzemux "$MOVIE"_premux.avi "$DEST"_fuze.avi \
&& rm "$MOVIE"_premux.avi
done
Wisdom from my inbox: "do not mock at your pottenocy"
User avatar
julian67
 
Posts: 4648
Joined: 2007-04-06 14:39
Location: Just hanging around


Return to Docs, Howtos, Tips & Tricks

Who is online

Users browsing this forum: No registered users and 4 guests

fashionable