How to run this tsduck shell command containing quotes with subprocess.run in Python

1.4k views Asked by At

Here is the command as written in the tsduck manual:

tsp -I dvb -a 1 @ts1028.txt \
     -P svremove -s AlJazeeraEnglish \
     -P merge "tsp -I dvb -a 0 @ts1022.txt -P zap TV5MondeEurope" \
     -P analyze -i 30 -o merged.txt \
     -O dektec @modulation.txt

Here is my version:

import sys
import subprocess

mod_values = { "bandwidth":             "8-mhz",
               "convolutional_rate":    "7/8",
               "frequency":             "578000000",
               "guard_interval":        "1/4",
               "dmb_constellation":     "64-QAM",
               "modulation":            "DVB-T"}

tsterinfo_rate = subprocess.run(['tsterinfo',
    "-h", mod_values["convolutional_rate"],
    "-g", mod_values["guard_interval"],
    "-c", mod_values["dmb_constellation"],
    "-s"], stdout=subprocess.PIPE, universal_newlines=True)

mod_values["dvb_bitrate"] = tsterinfo_rate.stdout

infile=sys.argv[1]

run_tsp = subprocess.run(['tsp',
    '--verbose',
    '-b', mod_values["dvb_bitrate"],
    '-I', 'null',
    '-P', 'merge',
        f'"tsp -I File {infile} --infinite"',
    '-P', 'pcrbitrate',
    '-P', 'regulate',
    '-O', 'dektec',
    '--frequency', mod_values["frequency"],
    '--modulation', mod_values["modulation"],
    '--guard-interval', mod_values["guard_interval"],
    '--convolutional-rate', mod_values["convolutional_rate"],
    '--dmb-constellation', mod_values["dmb_constellation"],
    '-s'])

The quoted part in the command returns this error if I try keeping it as full string with spaces in double quotes surround my single quotes:

/bin/sh: 1: tsp -I File ../Videos/myts.ts --infinite: not found

without the quotes at all it errors saying too many inputs the same as it would straight into the terminal without quotes

python 3.8.5, ubuntu 20.04

1

There are 1 answers

0
Jacob Smith On

I found a few things wrong with my tsp command when working through this. The answer to the question about passing quotes through to the sub-process seems to be solved by using

shell=True

In the sub-process options. Then you can pass the command line argument as one big string rather than as a list.

My final script for taking a transport stream as an argument and creating a CBR output ready for modulating through Dektec DTU-215 is this:

import sys
import subprocess
import json

# set modulation parameters in dict in order to reference once for bitrate calc and use again for modulator setup
mod_values = { "bandwidth":             "8-mhz",
               "convolutional_rate":    "7/8",
               "frequency":             "578000000",
               "guard_interval":        "1/4",
               "dmb_constellation":     "64-QAM",
               "modulation":            "DVB-T"}

# calculate modulated bitrate and add to dict
tsterinfo_rate = subprocess.run(['tsterinfo',
    "-h", mod_values["convolutional_rate"],
    "-g", mod_values["guard_interval"],
    "-c", mod_values["dmb_constellation"],
    "-s"], stdout=subprocess.PIPE, universal_newlines=True)

mod_values["dvb_bitrate"] = tsterinfo_rate.stdout.strip()

# first argument is input file transport stream
infile=sys.argv[1]

# use mediainfo to calculate bitrate of input ts (must be CBR)
infile_mediainfo = subprocess.run(["mediainfo",
    "--Output=JSON",
    infile],
    capture_output=True)

print(infile_mediainfo)

media_data = json.loads(infile_mediainfo.stdout)

ts_bitrate = int(media_data["media"]["track"][0]["OverallBitRate"])

print(f'ts_bitrate is: {ts_bitrate}')

# without -t option we don't have a PAT to even merge our stream with
# packet burst seems to make big difference to how smooth final playback is, default (16 according to docs) was jerky but 14 seems smooth
run_tsp = subprocess.run(f'tsp \
                --verbose \
                -d \
                -b {mod_values["dvb_bitrate"]} \
                -I null \
                -P regulate --packet-burst 14 \
                -P merge \
                -t \
                    "tsp -I file {infile} \
                    --infinite \
                    -P regulate -b {ts_bitrate}" \
                -O dektec \
                -f {mod_values["frequency"]} \
                -m {mod_values["modulation"]} \
                -g {mod_values["guard_interval"]} \
                -r {mod_values["convolutional_rate"]} \
                --dmb-constellation {mod_values["dmb_constellation"]} \
                -s', shell=True)