PDA

View Full Version : Qprocess error with script using ffmpeg



candau
31st July 2020, 12:43
Hi, I'm working on a project using a QProcess to call a script to segment video files using ffmpeg. The idea is to call within the script the command to segment a video file into many chunks of a few seconds, selected by the user. The script also converts the video file from mkv to mp4, but that does not seem to have any issues. I have tested the script from the command line and it works just fine, however when I call it with a QProcess in my code the video segments have a wrong length (should be 30 seconds but are of less than a second in duration).

The script has as arguments the directory of the video file and the duration of the segments, and is called from within a method like so:



QProcess *process = new QProcess();
connect(process, &QProcess::readyReadStandardError,
this, &GStreamerManager::readyReadStandardError);
connect(process, &QProcess::readyReadStandardOutput,
this, &GStreamerManager::readyReadStandardOutput);

QTime t;
t.restart();
QLOG_INFO() << "Segmenting video file into mp4 files...";
QStringList arguments;
arguments << video_finfo.absoluteFilePath()
<< QString::number(_params.video_split_interval_s);
QLOG_INFO() << arguments;
process->start("mkv2mp4s", arguments);
process->waitForFinished();
QLOG_INFO() << QString("Command %1 exited with code %2")
.arg(process->program()).arg(process->exitCode());
QLOG_INFO() << QString("MP4 converted! Delay %1 mseconds").arg(t.elapsed());



The script, mkv2mp4s goes like so:


#!/bin/bash

# Author: Leandro Candau Sánchez de Ybargüen
# Description: Split a mkv to many mp4 videos using ffmpeg
# Exit values: 0: No error | 1: Wrong arguments | 2: ffmpeg not installed | 3: Error mp4 split |
# 4: Error mp4 creation | 5: Error mkv split

function echo_error {
echo $1 1>&2
}

if [ $# -ne 2 ]; then
echo "Usage: $0 <path_to_video> <split_time_s>"
exit 1
fi

if ! command -v ffmpeg > /dev/null; then
echo_error "ffmpeg is not installed. Please install FFmpeg package."
exit 2
fi

input_mkv_path=$1
split_time_s=$2
exit_value=0
video_basename="$(dirname "$input_mkv_path")/$(basename "$input_mkv_path" .mkv)"
output_mp4_path="$(dirname "$input_mkv_path")/$(basename "$input_mkv_path" .mkv).mp4"
output_mp4_split="$(dirname "$input_mkv_path")/$(basename "$input_mkv_path" .mkv)_%d.mp4"
input_mkv_split="$(dirname "$input_mkv_path")/$(basename "$input_mkv_path" .mkv)_%d.mkv"

echo "Path to mkv: "$input_mkv_path""
echo "Video split seconds: "$split_time_s""
echo "Output mp4: "$output_mp4_path""
echo "Output mp4 split: "$output_mp4_split""

echo "Creating mp4 video $output_mp4_path from mkv $input_mkv_path..."
{
ffmpeg -i $input_mkv_path -codec copy $output_mp4_path
} &> /dev/null

if test -f "$output_mp4_path"; then
echo "New video file "$output_mp4_path" has been created"
echo "Removing old mkv file..."
rm $input_mkv_path
echo "Spliting mp4 file in "$split_time_s" seconds chunks"
{
ffmpeg -i $output_mp4_path -c copy -segment_time $split_time_s -f segment $output_mp4_split
} &> /dev/null
if ls ""$video_basename"_0.mp4" 1> /dev/null 2>&1; then
echo "Removing old mp4 file..."
rm $output_mp4_path
else
echo_error "Split files do not exist!"
exit_value=3
fi
else
echo_error "mp4 creation failed!"
exit_value=4
echo "Spliting mkv file in "$split_time_s" seconds chunks"
{
ffmpeg -i $input_mkv_path -c copy -segment_time $split_time_s -f segment $input_mkv_split
} &> /dev/null
if ls ""$video_basename"_0.mkv" 1> /dev/null 2>&1; then
echo "Removing old mkv file..."
rm $input_mkv_path
else
echo_error "Split mkv files do not exist!"
exit_value=5
fi
fi

# Format the file name from basefile_<0|1|2...>.mp4|mkv to basefile_<offset_seconds>.mp4|mkv
for filename in $(dirname "$input_mkv_path")/$(basename "$input_mkv_path" .mkv)_*.m*; do
substring=$(echo $filename | grep -oP "_\d+\.") # substring con el patron _#.
value=$(echo $substring | grep -oP "\d+") # valor de # del string anterior
value=_$(( $value*$split_time_s )). # valor # * split_time_s
new_filename=${filename/$substring/$value}
if [ $new_filename != $filename ]; then # evita warning en el _0 pq se llama igual
mv $filename ${filename/$substring/$value} # el string original reemplazando substring por _value.
fi
done

exit $exit_value

I would appreciate any insight on how to deal with this. Thanks.

d_stranz
31st July 2020, 15:24
QString::number(_params.video_split_interval_s);

Create a temporary variable to hold the value of this expression then examine it in the debugger as well as the value of the input (_params.video_split_interval).

candau
5th August 2020, 09:26
Hi! Thanks for the reply! I tried debugging as you suggested and saw naught was wrong with the script, as I saw when trying to run it manually.
Eventually I traced the error onto the next processing point of the video, witch was another script to add metadata into it renaming the video. The problem was in this second script for it renames the video before it was done copying it, thus resulting in an incomplete video. Thanks for the help!