Search code examples
javaspringruntimeexec

Java Runtime cmd execution in a Spring Boot project


A project consists of audio blocks. I'm implementing REST API that updates project when there is change in blocks.
I would like to merge blocks with paddings between the audio blocks, and then upload appended audio back to S3 storages. Audio files are stored in S3 storages. I want to execute sox command while running a spring boot project in an EC2. sox module is installed in an EC2 instance. Would this be a problem of directory path?

When I call the function it returns exit value 1, and audio blockes are not merged with paddings. I tried executing same runtime command in a simple java file and it worked, but it is not working in a deployed spring boot project.

public void mergeBlocks(Long teamId, Long projectId){
        try {
            List<Block> blocks = blockRepository.findByProjectId(projectId);
            long length = 0;
            AudioInputStream clip = null;
            List<AudioInputStream> list = new ArrayList<AudioInputStream>();
            new File(String.valueOf(projectId)).mkdirs();
            for (Block b: blocks) {
                FileOutputStream fos = new FileOutputStream(new File(projectId + "/temp" + b.getId() + ".wav"));
                S3Object o = amazonS3Client.getObject(AUDIO_BUCKET_NAME, teamId + "/" + projectId + "/" + b.getId() + ".wav");
                S3ObjectInputStream s3is = o.getObjectContent();
                byte[] read_buf = new byte[1024];
                int read_len = 0;
                while ((read_len = s3is.read(read_buf)) > 0) {
                    fos.write(read_buf, 0, read_len);
                }
                fos.close();
                String[] cmd = {"sox", projectId + "\\temp" + b.getId() + ".wav", projectId + "\\interval" + b.getId() + ".wav", "pad", "0", String.valueOf(b.getInterval())};
                try {
                    Runtime rt = Runtime.getRuntime();
                    Process pr = rt.exec(cmd);
                    BufferedReader input = new BufferedReader(new InputStreamReader(pr.getInputStream()));

                    String line = null;

                    while ((line = input.readLine()) != null) {
                        System.out.println(line);
                    }

                    int exitVal = pr.waitFor();
                    System.out.println("Exited with error code " + exitVal);
                } catch(Exception e) {
                    System.out.println(e.toString());
                    e.printStackTrace();
                }

                clip = AudioSystem.getAudioInputStream(new File(projectId + "/interval" + b.getId() + ".wav"));
                list.add(clip);
                length += clip.getFrameLength();
            }
            if(length>0 && list.size()>0 && clip!=null) {
                AudioInputStream appendedFiles =
                        new AudioInputStream(
                                new SequenceInputStream(Collections.enumeration(list)),
                                clip.getFormat(),
                                length);

                AudioSystem.write(appendedFiles,
                        AudioFileFormat.Type.WAVE,
                        new File(projectId + "/appended.wav"));
            }
            clip.close();
            amazonS3Client.putObject(AUDIO_BUCKET_NAME, teamId + "/" + projectId + "/0.wav", new File(projectId + "/appended.wav"));
            FileUtils.deleteDirectory(new File(String.valueOf(projectId)));
        } catch (AmazonServiceException e) {
            System.err.println(e.getErrorMessage());
            System.exit(1);
        } catch (FileNotFoundException e) {
            System.err.println(e.getMessage());
            System.exit(1);
        } catch (IOException e) {
            System.err.println(e.getMessage());
            System.exit(1);
        } catch (UnsupportedAudioFileException e) {
            e.printStackTrace();
        }
    }

I tried executingn sox command with java Runtime.getRuntime().exec(cmd); I expected sox command getting executed successfully while running the spring boot project.


Solution

  • The problem might lie therein, that you are using backslashes to specify the directory paths. While you are correctly escaping them in your code. The string for your command will still look like: "yourProjectId\temp\..., which might still cause errors when executed. Try using forward slashes / instead or maybe using double escaped backslashes like \\\\.