Take the 2-minute tour ×
Unix & Linux Stack Exchange is a question and answer site for users of Linux, FreeBSD and other Un*x-like operating systems.. It's 100% free, no registration required.

How can I add an audio file (OGG vorbis) into a shell script making the script as small as possible and at the same time being able to execute it on as most systems as possible? I want the audio file be played.

I don’t want it to be uuencoded, because sharutils are not installed on many systems. base64 is nice, but makes the file/script bigger, which I don’t want.

Should I use mplayer or the play command from the sox package? Is it more common on Linux/BSD systems? Or is there another media player mostly installed? Should I convert the audio file to another format/codec (if that doesn’t make the file much bigger) to have more possible players to play the file back or is OGG vorbis a good choice?

share|improve this question

2 Answers 2

up vote 0 down vote accepted

With the following script it works (using mplayer, which is probably not present on many systems).

#!/bin/sh
grep -A 1000 --text -m 1 ^Ogg "$0" | mplayer -
exit
OggS^@^B^@^@^@^@^@^@^@^@^]f<8a>g^@^@^@^@lY߸^A^^^Avorbis^@^@^@^@^A"V^@^@^...

The last line is the beginning of the audio file binary.

The grep command searches for the first occurrence of Ogg in the file $0 (which is the script file itself) and prints 1000 lines after that line (is enough for my small audio test file). The output of grep is then piped to mplayer which is reading /dev/stdin (abbreviation for /dev/stdin is -).

I have created this file by concatenating the script file playmeBashScript.sh with the audio file sound.ogg:

cat playmeBashScript.sh sound.ogg > playme.sh

A more general and a bit shorter version with sed instead of grep (thanks to Elias):

#!/bin/sh
sed 1,/^exit$/d "$0" | mplayer -
exit
OggS^@^B^@^@^@^@^@^@^@^@^]f<8a>g^@^@^@^@lY߸^A^^^Avorbis^@^@^@^@^A"V^@^@^...

In this case sed selects all lines from number one up to the line where it finds the word exit and deletes them. The rest is pasted and piped to mplayer. Of course that only works if the word exit occurs only once in the script before the binary data.

share|improve this answer
    
It will probably be better to use sed 1,/^Ogg/d "$0" | mplayer - instead. –  elias Feb 7 at 16:24
    
@elias no that does not work. The Ogg is part of the audio file (the first three bytes of it) and your command deletes this line (as far as I understand it). If I apply your command to my playme.sh file, the output is to small, does not play. –  erik Feb 7 at 16:42
    
oh, alright, then maybe using another separator and then using: sed 1,/^BEGIN_FILE/d "$0" | mplayer -. I just thought it could be a more general solution. =) –  elias Feb 7 at 16:44
    
Yes, ok. That is more general than having to tweak the number of output lines at grep’s -A option. I will change my answer. –  erik Feb 7 at 16:46

Your script should contain also the concatenated data:

#!/bin/sh

TMPFILE=$(mktemp)
trap "rm ${TMPFILE}" 0 1 2 3 11 15
tail -n +7 $0 ${TMPFILE}
exec mplayer ${TMPFILE}

Let's call the script omniplay. So you need to cat your ogg-file appending to the script:

cat file.ogg >> omniplay
chmod +x omniplay
./omniplay

This is a standard method used by many install.sh files. Look also for gzexe. You may also adjust the tail lines.

share|improve this answer
    
Has your version any advantages over my version? I don’t like it because it is longer. And I’d rather read the data directly from the file instead of writing it into a temporary file. Imagine the media file is 10 GB in size. Not a good idea to put that into a temporary file first. –  erik Feb 7 at 17:06

Your Answer

 
discard

By posting your answer, you agree to the privacy policy and terms of service.

Not the answer you're looking for? Browse other questions tagged or ask your own question.