You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Spring Boot项目执行Sox命令失败(退出码1)问题排查

问题

我的项目包含音频块,正在实现REST API以在音频块发生变更时更新项目。需要将音频块合并并在块间添加间隔,之后将合并后的音频上传回S3存储(音频文件存储于S3中)。我在EC2上运行的Spring Boot项目中执行已安装的Sox命令,但调用函数时返回退出码1,音频块未完成带间隔的合并。在普通Java文件中执行相同Runtime命令可正常运行,但部署后的Spring Boot项目中无法正常工作,相关代码如下:

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();
        }
    }

我尝试使用Java Runtime.getRuntime().exec(cmd)执行Sox命令,期望在Spring Boot项目中能成功执行该命令,请问是否是目录路径的问题?

回答

  • 路径分隔符不匹配:你在代码里混合使用了两种路径分隔符——创建临时文件用的是/,但Sox命令里用的是\\。EC2通常运行Linux系统,路径分隔符是/,\\是Windows的分隔符,这会导致Sox找不到输入文件,直接返回错误码1。把Sox命令里的\\全部改成/即可解决这个核心问题。
  • 工作目录差异:普通Java程序和Spring Boot部署后的工作目录不同。普通Java程序的工作目录是你运行命令的目录,而Spring Boot以jar包运行时,工作目录可能是jar所在目录或Tomcat临时目录。建议使用绝对路径创建临时目录和文件(比如/tmp/下的子目录),避免依赖当前工作目录。
  • 未捕获Sox错误输出:你只读取了Sox的标准输出,但错误信息会输出到标准错误流。添加以下代码读取错误流,能看到Sox具体的错误提示,更易定位问题:
    BufferedReader errorReader = new BufferedReader(new InputStreamReader(pr.getErrorStream()));
    String errorLine;
    while ((errorLine = errorReader.readLine()) != null) {
        System.err.println("Sox错误输出:" + errorLine);
    }
    
  • 权限问题:Spring Boot运行的用户(如tomcat用户、ec2-user)可能没有临时目录的读写权限,或没有执行Sox命令的权限。检查临时目录权限,确保运行用户有读写权限;同时确认Sox命令的路径在该用户的环境变量PATH中,或直接使用Sox的绝对路径(比如/usr/bin/sox)执行命令。

内容的提问来源于stack exchange,提问作者tlfdksro

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.25 00:32:38