How to execute this particular shell command from Python?

6,156

Your question is long and rambling and I don't know what you expect for an answer. Going by your title, I think your focus is on this fragment of Python code:

lineone = linecache.getline(filename, i)
os.system("echo " + lineone + "|" + "festival --tts")

Your problem is that lineone is the whole line, including the final newline. You need to, as they say in Perl land, chomp it.

lineone = linecache.getline(filename, i).rstrip('\n')
os.system("echo " + lineone + "|" + "festival --tts")

Your first shell script looks awfully complicated and slow for what it does. Why are you computing the number of lines, then retrieving the lines by number in order? You could simply read the input one line at a time, like you do in Python.

while IFS= read -r line; do
  echo "$line" | text2wave -o temp.wav
  sox "otherstuff.wav" "temp.wav" "silence.wav" "output.wav"
  mv output.wav otherstuff.wav
  rm temp.wav
done

You should be able to simplify this further by using raw audio files, that do not contain a header and so can be concatenated:

while IFS= read -r line; do
  echo "$line" | text2wave -otype raw >>otherstuff.raw
  cat silence.raw >>otherstuff.raw
done
sox … otherstuff.raw otherstuff.wav

You'll need to tell sox what parameters (such as sampling depth) the raw audio file is encoded in.

Share:
6,156

Related videos on Youtube

Matthew
Author by

Matthew

Updated on September 18, 2022

Comments

  • Matthew
    Matthew over 1 year

    OK, so, I have this non-functional shell script, which I am rewriting piece by piece in python, except I am getting an "unexpected "|" error" from the shell (see below):

    #/bin/sh
    LINES=`cat $@ | wc -l`
    
    for i in `seq 1 $lines`; do
    
    head -n $i $@ | tail -n 1 | text2wave -o temp.wav
    sox "otherstuff.wav" "temp.wav" "silence.wav" "output.wav"
    mv output.wav otherstuff.wav
    rm -rf temp.wav
    
    done
    

    Which isn't really feasible in practice. But if I know the number of lines in a file, I can run it on a particular file to TTS the entire file and insert 10 seconds of silence between each line, because I don't have to say

    LINES=`cat $@ | wc -l`
    

    In the interest of flow control, and a way of incorporating the line count into a script I can use everywhere, am going to use Python to do this job. So far I have this fragment, also non-functional:

    import linecache, os
    
    for i in range(linelength):
        lineone = linecache.getline(filename, i)
        os.system("echo " + lineone + "|" + "festival --tts")
    

    which gives this error in the IPython interpreter:

    d 68.
    sh: 2: Syntax error: "|" unexpected
    Out[60]: 512
    d 67.
    sh: 2: Syntax error: "|" unexpected
    Out[60]: 512
    c 52.
    sh: 2: Syntax error: "|" unexpected
    Out[60]: 512
    c 42.
    sh: 2: Syntax error: "|" unexpected
    Out[60]: 512
    c 71.
    sh: 2: Syntax error: "|" unexpected
    Out[60]: 512
    c 51.
    sh: 2: Syntax error: "|" unexpected
    Out[60]: 512
    c 19.
    sh: 2: Syntax error: "|" unexpected
    Out[60]: 512
    c 18.
    sh: 2: Syntax error: "|" unexpected
    Out[60]: 512
    b 16.
    sh: 2: Syntax error: "|" unexpected
    Out[60]: 512
    b 15.
    sh: 2: Syntax error: "|" unexpected
    Out[60]: 512
    b 1.
    sh: 2: Syntax error: "|" unexpected
    Out[60]: 512
    d 16.
    sh: 2: Syntax error: "|" unexpected
    Out[60]: 512
    d 14.
    sh: 2: Syntax error: "|" unexpected
    Out[60]: 512
    a 96.
    sh: 2: Syntax error: "|" unexpected
    Out[60]: 512
    a 95.
    sh: 2: Syntax error: "|" unexpected
    Out[60]: 512
    a 35.
    sh: 2: Syntax error: "|" unexpected
    Out[60]: 512
    a 25.
    sh: 2: Syntax error: "|" unexpected
    Out[60]: 512
    d 74.
    sh: 2: Syntax error: "|" unexpected
    Out[60]: 512
    d 83.
    sh: 2: Syntax error: "|" unexpected
    Out[60]: 512
    a 9.
    sh: 2: Syntax error: "|" unexpected
    Out[60]: 512
    d 9.
    sh: 2: Syntax error: "|" unexpected
    Out[60]: 512
    b 97.
    sh: 2: Syntax error: "|" unexpected
    Out[60]: 512
    b 99.
    sh: 2: Syntax error: "|" unexpected
    Out[60]: 512
    b 76.
    sh: 2: Syntax error: "|" unexpected
    Out[60]: 512
    b 77.
    sh: 2: Syntax error: "|" unexpected
    Out[60]: 512
    d 89.
    sh: 2: Syntax error: "|" unexpected
    Out[60]: 512
    d 99.
    sh: 2: Syntax error: "|" unexpected
    Out[60]: 512
    b 94.
    sh: 2: Syntax error: "|" unexpected
    Out[60]: 512
    d 54.
    sh: 2: Syntax error: "|" unexpected
    Out[60]: 512
    d 66.
    sh: 2: Syntax error: "|" unexpected
    Out[60]: 512
    c 81.
    sh: 2: Syntax error: "|" unexpected
    Out[60]: 512
    c 61.
    sh: 2: Syntax error: "|" unexpected
    Out[60]: 512
    

    and which replicates

    for i in `seq 1 $lines`; do
    
    head -n $i $@ | tail -n 1 | text2wave -o temp.wav
    

    but is handier for testing everything, because it simply reads it out (festival and text2wave are part of the same package, one reads things out and the other writes files)...

    now, the number of lines being already retrieved and stored in linelength (I didn't have a problem getting python to do that):

    If it were simply

    for i in range(linelength):
        lineone = linecache.getline(filename, i)
        os.system("echo somestuffnotaline | festival --tts")
    

    then festival would say "somEhstuffnotaLINE", but I would not be as happy as I would if it would say, "c 62" -- "d 74" -- etc, those being the contents of each line in the files I am processing.

  • Matthew
    Matthew over 12 years
    you're right that i was rambling. i was rambling because 'he who speaks does not know'. thank you so much for those three very valuable pieces of advice. should be worth 3 upvotes really. hurray!
  • Matthew
    Matthew over 12 years
    the joys of IFS!
  • South Coast Web
    South Coast Web almost 10 years
    Note for posterity: I think input here should be import, though I'm not running it so I'm reluctant to edit the answer directly.