gpt4 book ai didi

java - java中的录音机问题

转载 作者:行者123 更新时间:2023-12-01 15:58:37 25 4
gpt4 key购买 nike

我在录制音频时遇到问题。我创建了一个servlet,并对java sound API演示代码进行了一定程度的修改,最后我可以录制音频了。问题是,当我播放音频时,我可以看到存储为 645.45 或类似内容的音频总时间,但我只录制了几分钟的音频。还有一个问题是音频保存在 Eclipse 目录而不是项目目录中。

这是 servlet 代码。

package com;

import java.io.ByteArrayInputStream;
import java.io.ByteArrayOutputStream;
import java.io.File;
import java.io.IOException;
import java.io.InputStream;

import javax.servlet.ServletException;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import javax.sound.sampled.AudioFileFormat;
import javax.sound.sampled.AudioFormat;
import javax.sound.sampled.AudioInputStream;
import javax.sound.sampled.AudioSystem;
import javax.sound.sampled.DataLine;
import javax.sound.sampled.Clip;
import javax.sound.sampled.LineUnavailableException;
import javax.sound.sampled.SourceDataLine;
import javax.sound.sampled.TargetDataLine;

public class SoundRecorder extends HttpServlet {

private static final long serialVersionUID = 1L;

static protected boolean running;
static ByteArrayOutputStream out;
double fileName = Math.random();
//strFilename = nowLong.toString();



public SoundRecorder() {
System.out.println("Filename will be..." + fileName + ".wav");
}

public void init() {

}

public void destroy() {

}


public void doGet(HttpServletRequest request, HttpServletResponse response)
throws ServletException, IOException {
System.out.println("call received..");
String method = request.getParameter("method");
System.out.println(method);
if("record".equalsIgnoreCase(method)) {
captureAudio(true);
}
else if("stop".equalsIgnoreCase(method)) {
captureAudio(false);
}
else if("play".equalsIgnoreCase(method)) {
System.out.println("yet to write");
playAudio();
}
}

public void doPost(HttpServletRequest request, HttpServletResponse response)
throws ServletException, IOException {
System.out.println("call received..");
String method = request.getParameter("method");
System.out.println(method);
doGet(request, response);
}

private void captureAudio(boolean capturing) {


File outputFile = new File(fileName + ".wav");
AudioFormat audioFormat = new AudioFormat(AudioFormat.Encoding.PCM_SIGNED,44100.0F, 16, 2, 4, 44100.0F, false);

DataLine.Info info = new DataLine.Info(TargetDataLine.class, audioFormat);
TargetDataLine targetDataLine = null;

try
{
targetDataLine = (TargetDataLine) AudioSystem.getLine(info);
targetDataLine.open(audioFormat);
}
catch (LineUnavailableException e)
{
System.out.println("unable to get a recording line");
e.printStackTrace();
System.exit(1);
}

AudioFileFormat.Type targetType = AudioFileFormat.Type.WAVE;

final Recorder recorder = new Recorder(targetDataLine,targetType,outputFile);

System.out.println("Recording...");
if(capturing){
recorder.start();
}
else {
recorder.stopRecording();
}

}



private void playAudio() {
try {
File file = new File(fileName + ".wav");
AudioInputStream stream = AudioSystem.getAudioInputStream(file);
AudioFormat format = stream.getFormat();
DataLine.Info info = new DataLine.Info(Clip.class, stream.getFormat());
Clip clip = (Clip) AudioSystem.getLine(info);
clip.open(stream);
clip.start();
} catch (Exception e) {
System.err.println("Line unavailable: " + e);
System.exit(-4);
}
}
}

这是记录器类

public class Recorder extends Thread {
private TargetDataLine m_line;
private AudioFileFormat.Type m_targetType;
private AudioInputStream m_audioInputStream;
private File m_outputFile;

public Recorder(TargetDataLine line,
AudioFileFormat.Type targetType,
File file)
{
m_line = line;
m_audioInputStream = new AudioInputStream(line);
m_targetType = targetType;
m_outputFile = file;
}

/** Starts the recording.
To accomplish this, (i) the line is started and (ii) the
thread is started.
*/
public void start()
{
m_line.start();
super.start();
}

/** Stops the recording.
*/
public void stopRecording()
{
m_line.stop();
m_line.close();
}

/** Main working method.
*/
public void run()
{
try
{
AudioSystem.write(
m_audioInputStream,
m_targetType,
m_outputFile);
}
catch (IOException e)
{
e.printStackTrace();
}
}

private static void closeProgram()
{
System.out.println("Program closing.....");
System.exit(1);
}

private static void out(String strMessage)
{
System.out.println(strMessage);
}


}

最佳答案

使用 Servlet 进行开发时,您需要意识到,在整个 Web 应用程序的生命周期(从启动到关闭)中只有一个 Servlet 实例。因此,来自所有访问者、所有 session 、所有浏览器窗口/选项卡等的 HTTP 请求都将共享相同 servlet 实例。另外,当您创建一个静态变量时,它将在同一类的所有实例之间共享(这在这里并不真正相关,因为无论如何只有一个 servlet 实例)。

换句话说,您在 servlet 中声明的那些变量不是线程安全的:

static protected boolean running;
static ByteArrayOutputStream out;
double fileName = Math.random();

只有其中一个,并且可供所有访问者同时使用。对于不断修改的前两个变量,这将导致主要的线程安全问题,而对于第三个变量,这意味着所有访问者都会记录到同一个文件。您需要在 doGet() block 内声明它们。您希望通过基于唯一请求的 token 作为 key 将录音存储在 session 中,然后将该 key 传递给后续请求。

<小时/>

关于文件保存在非预期位置的问题;当您在 servlet 中的 java.io.File 中使用相对路径时,它将相对于 Web 服务器启动的目录。如果从 Eclipse 内部启动它,那么它会保存在 Eclipse 目录中。您想在 java.io.File 中使用绝对路径。如果您的目的是将其保存在公共(public) web 内容中(您的 JSP 和 /WEB-INF 文件夹所在的位置),那么您需要 ServletContext#getRealPath() 进行转换绝对磁盘路径的 Web 路径。

String relativeWebPath = "filename.ext";
String absoluteDiskPath = getServletContext().getRealPath(relativeWebPath);
File file = new File(absoluteDiskPath);

然而,这还有另一个问题:每当您重新部署 Web 应用程序时,所有文件都会被删除。如果您想要更多的永久存储,那么您希望将其存储在 Web 项目之外。例如。 C:/path/to/recordings

File file = new File("C:/path/to/recordings/filename.ext");

关于java - java中的录音机问题,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/4479893/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com