JT808,JT1078协议,Java获取音频数据播放时长

在java编程中,可以根据 .wav 或者PCM 字节的长度,算出音频数据播放的时长。

java 复制代码
		try
		{
			AudioInputStream audioInputStream = AudioSystem.getAudioInputStream(new File("F:\\20250926_101326.wav"));
			AudioFormat format = audioInputStream.getFormat();
			// 算法一
			long frames = audioInputStream.getFrameLength(); // 帧总数
			float frameRate = format.getFrameRate();  // 每秒播放的帧数
			float durationInSeconds = frames / frameRate;
			// 时长(秒)= 文件大小(字节) / 采样率 / 采样通道 / 每个采样点几个字节
			// ‌时长(秒)= 文件字节数 ÷ (采样率 × 声道数 × 每个采样点字节数)
			long fileLength = audioInputStream.getFrameLength() * format.getFrameSize();
			float sampleRate = format.getSampleRate();
			int channels = format.getChannels();
			int bitDepth = format.getSampleSizeInBits() / 8; // 每个样本多少位
			BigDecimal pcmDur1 = new BigDecimal(fileLength)
					.divide(new BigDecimal(sampleRate),11, RoundingMode.HALF_UP)
					.divide(new BigDecimal(channels),11,RoundingMode.HALF_UP)
					.divide(new BigDecimal(bitDepth),11, RoundingMode.HALF_UP);
		    BigDecimal pcmDur2 =	new BigDecimal(fileLength).divide(new BigDecimal(sampleRate * channels * bitDepth),11,RoundingMode.HALF_UP);
		}
		catch (Exception xx) {
            String xvx = "";
		}

实时解码AAC音频:

java 复制代码
import net.sourceforge.jaad.aac.Decoder;
import net.sourceforge.jaad.aac.SampleBuffer;
import net.sourceforge.jaad.adts.ADTSDemultiplexer;
import org.bytedeco.ffmpeg.global.avcodec;
import org.bytedeco.javacv.FFmpegFrameRecorder;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import javax.sound.sampled.*;
import java.io.*;
import java.nio.ByteBuffer;
import java.nio.ByteOrder;
import java.nio.ShortBuffer;
import java.nio.file.Files;
import java.nio.file.Paths;
import java.nio.file.StandardOpenOption;


		// 播放 AAC
		SourceDataLine line1 = null;
		byte[] b1;
		try {
			final ADTSDemultiplexer adts = new ADTSDemultiplexer(new FileInputStream("F:\\kk001.aac"));
			final Decoder dec = new Decoder(adts.getDecoderSpecificInfo());
			final SampleBuffer buf = new SampleBuffer();
			while(true) {
				b1 = adts.readNextFrame();
				dec.decodeFrame(b1, buf);
				if(line1==null) {
					final AudioFormat aufmt = new AudioFormat(buf.getSampleRate(), buf.getBitsPerSample(), buf.getChannels(), true, true);
					line1 = AudioSystem.getSourceDataLine(aufmt);
					line1.open();
					line1.start();
				}
				b1 = buf.getData();
				line1.write(b1, 0, b1.length);
			}
		} catch (Exception ex) {
			if(line1!=null) {
				line1.stop();
				line1.close();
			}
		}




	// PCM 转 AAC
		try{
			AudioFormat format = new AudioFormat(Float.valueOf(8000), 16, 1, true, false);
			ByteArrayOutputStream outputStream = new ByteArrayOutputStream();
			FFmpegFrameRecorder recorder = new FFmpegFrameRecorder(outputStream, format.getChannels());
			recorder.setSampleRate((int)format.getSampleRate()); // 设置采样率
			recorder.setFrameRate(format.getFrameRate());   // 设置帧率与原始设备相同
			recorder.setAudioCodec(avcodec.AV_CODEC_ID_PCM_S16LE);
			recorder.setAudioCodecName("aac");
			recorder.setFormat("adts");
			recorder.start();
			TargetDataLine line = (TargetDataLine) AudioSystem.getLine(new DataLine.Info(TargetDataLine.class, format));
			line.open(format);
			line.start();
			int sampleRate = (int) format.getSampleRate();
			int numChannels = format.getChannels();
			byte[] buffer = new byte[sampleRate * numChannels];

			int times = 0;

			while (!Thread.interrupted() && times <  200) {
				times++;
				int nBytesRead = 0;
				while (nBytesRead == 0) {
					nBytesRead = line.read(buffer, 0, line.available());
				}
				int nSamplesRead = nBytesRead / 2;
				short[] samples = new short[nSamplesRead];
				ByteBuffer.wrap(buffer).order(ByteOrder.LITTLE_ENDIAN).asShortBuffer().get(samples);
				ShortBuffer sBuff = ShortBuffer.wrap(samples, 0, nSamplesRead);
				recorder.recordSamples(sampleRate, numChannels, sBuff);
			}
			recorder.flush();
			byte[] result = outputStream.toByteArray();
			Files.write(Paths.get("F:\\ddd.aac"), result, StandardOpenOption.CREATE);
			String yy = "yy";
		}catch (Exception ec) {
			String yy = "yy";
		}






        // 实时接收数据并转码,存储
		ByteArrayOutputStream outputStream = new ByteArrayOutputStream();
		try {
			// 前端传PCM数据转WAV: sampleRate:采样率,sampleSizeInBits:采样位数,channels:声道数 1=单声道 2=双声道,signed:数据有无符号,bigEndian:是否为大端模式
			AudioFormat pcmFormat = new AudioFormat(8000, 16, 1, true, false);
			outputStream.write(pcmData);
			byte[] result = outputStream.toByteArray();
			Integer len2 = result.length;
			if(len2 > 100 * 1364) {
				// 转换成 WAV
				InputStream testInputStream = new ByteArrayInputStream(result);
				AudioInputStream testAudioInputStream = new AudioInputStream(testInputStream,pcmFormat, result.length   );
				OutputStream fos = Files.newOutputStream(Paths.get("F:\\test01.wav"), StandardOpenOption.CREATE);
				AudioSystem.write(testAudioInputStream, AudioFileFormat.Type.WAVE, fos);
				testAudioInputStream.close();
				fos.close();
				// 转换成 AAC
				outputStream.reset(); // 清空数据
			}
			InputStream inputStream = new ByteArrayInputStream(pcmData);
			AudioInputStream audioInputStream = new AudioInputStream(inputStream, pcmFormat, pcmData.length );
			// 前端传 wav 格式的数据,可以直接读取
			// AudioInputStream audioInputStream = AudioSystem.getAudioInputStream(inputStream);
			// 直接播放
			// Clip clip = AudioSystem.getClip();
			// clip.open(audioInputStream);
			// clip.start();
			// inputStream.close(); //关闭流
		} catch (Exception ee) {
			String xx = ee.getMessage();
			ee.getStackTrace();
		}