从数据库中获取配置好的语音文件信息数组,然后播放,播放中如果有紧急广播,则终止当前的,播放紧急的;
在此,将语音数组进行合并成一条语音,否则不好控制,另外没有使用线程阻塞和多线程,一方面是不好控制,另一方面是效果很不好,所以在这里加了一个文件结束日期,当播放语音开始时,获取文件时长,然后得到该文件播放完的结束日期,如果在结束日期之前再来广播,则不播放(可在此配置队列进行排队机制,我没加^_^),如果来了紧急广播,则终止当前正在播放的,来播放紧急语音,所以在每次广播之前都要先判断一下,当前时间是否在结束日期之前;
将amr转为wav的过程中,可能有报错,但是不影响使用,报错说时长等属性为空,但是我设置后还是为提示空,暂时没管这个错;
import it.sauronsoftware.jave.AudioAttributes;
import it.sauronsoftware.jave.Encoder;
import it.sauronsoftware.jave.EncoderException;
import it.sauronsoftware.jave.EncodingAttributes;
import it.sauronsoftware.jave.InputFormatException;
import java.io.File;
import java.io.FileInputStream;
import java.io.IOException;
import java.io.SequenceInputStream;
import java.text.DateFormat;
import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.Collections;
import java.util.Date;
import java.util.Enumeration;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Properties;
import javax.sound.sampled.AudioFileFormat;
import javax.sound.sampled.AudioFormat;
import javax.sound.sampled.AudioInputStream;
import javax.sound.sampled.AudioSystem;
import javax.sound.sampled.Clip;
import javax.sound.sampled.LineUnavailableException;
import javax.sound.sampled.UnsupportedAudioFileException;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.ljy.common.shcedule.ScheduledJob;
import com.ljy.entity.TB_YYK_VO;
import com.ljy.util.PropertiesUtil;
import sun.audio.AudioPlayer;
import sun.audio.AudioStream;
@RestController
@RequestMapping("/radio")
public class ReadWav {
private FileInputStream fileau = null;
private String stop_date = getNowTime(); //文件播放的结束时间,初始化为当前时间
private static String allWav_name = "allWav_playing.wav"; //合并后的语音文件名称
private static String talk_name = "talking.wav"; //紧急口播生成的文件名称
private static String loop_num = "2"; //默认循环
private static boolean is_replace = false; //是否下次语音覆盖正在播放的语音
private final static Logger logger = LoggerFactory.getLogger(ScheduledJob.class);
//也可以从配置文件中读取
static{
try {
Properties pro = PropertiesUtil.getProperties("Config.properties");
allWav_name = pro.getProperty("allWav_name");
talk_name = pro.getProperty("talk_name");
loop_num = pro.getProperty("loop_num");
is_replace = Boolean.parseBoolean(pro.getProperty("is_replace"));
} catch (Exception e) {
e.printStackTrace();
}
}
//lujing:需要播放的语音文件路径数组JSON,按顺序排好,cs:播放次数
@RequestMapping("/wav")
public void ReadWavs(String lujing,String cs) throws IOException, LineUnavailableException,
UnsupportedAudioFileException, InterruptedException{
//如果在播放时间再次播放,则直接返回不播放
if(!is_replace && compare_date(getNowTime(),stop_date) == -1){
logger.info("当前有正在播放语音,本次播放禁止!");
return ;
}
//JSON转为实体类
TB_YYK_VO[] lists = new ObjectMapper().readValue(lujing, TB_YYK_VO[].class);
//如果没传次数,则使用默认
if(cs == null || "".equals(cs)){
cs = loop_num ;
}
int num = Integer.parseInt(cs);
AudioFormat format = null;
AudioFileFormat aff = null ;
AudioInputStream ais = null ;
long frameLength = 0; //文件帧数
ArrayList c = new ArrayList();
//播放次数
for(int i=0;i//语音文件数组
for(int j=0;jnew File(adress);
ais = AudioSystem.getAudioInputStream(ccy);
//获取语音文件的属性信息,只获取一次即可
if(j == 0){
aff = AudioSystem.getAudioFileFormat(ccy);
format = ais.getFormat();
}
//需要将长度相加,不然时长不对
frameLength += ais.getFrameLength();
c.add(ais);
}
}
Enumeration e = Collections.enumeration(c);
SequenceInputStream sis = new SequenceInputStream(e);
AudioInputStream all = new AudioInputStream(sis, format,frameLength) ;
AudioSystem.write(all,aff.getType(), new File(allWav_name));
//需要播放的语音文件流
fileau = new FileInputStream(allWav_name);
long wav_time = CalculationTime(allWav_name)*1000+10; //文件时长
stop_date = getDateByAdd((int)wav_time); //文件播放完的日期
AudioPlayer.player.start(fileau);
}
//停止播放
@RequestMapping("/stopWav")
public void stopWav() throws Exception{
logger.info("停止了当前播放语音");
AudioPlayer.player.stop(fileau);
stop_date = getNowTime() ; //结束播放后,将文件播放结束日期置为当前即可
}
//紧急口播
//filePath:生成的amr路径
@RequestMapping("/playVideo")
public void playVideo(String filePath,String duration) throws Exception{
logger.info("口播语音filename:---"+filePath);
//口播优先级最高,所以直接中断当前广播
AudioPlayer.player.stop(fileau);
changeToWav(filePath,talk_name,new Float(duration)); //格式转换
fileau = new FileInputStream(talk_name);
long wav_time = CalculationTime(talk_name)*1000+10; //文件时长
stop_date = getDateByAdd((int)wav_time); //文件播放完的日期
AudioPlayer.player.start(fileau);
}
/**
*
* 下面是一些服务方法
*------------------------------------------------------------------------------------------
*/
/**
*
* @Title: changeToWav
* @Description: TODO(将语音文件转为wav格式)
* @param @param sourcePath 源文件路径
* @param @param targetPath 转换后的文件路径
* @param @param duration 文件时长(这个从手机端传过来的参数值,但是使用了没效果)
* @return void 返回类型
* @throws
*/
public static void changeToWav(String sourcePath, String targetPath,Float duration) {
try {
File source = new File(sourcePath);
File target = new File(targetPath);
AudioAttributes audio = new AudioAttributes();
Encoder encoder = new Encoder();
audio.setCodec("pcm_s16le");
audio.setBitRate(new Integer(705000));
audio.setChannels(new Integer(1));
audio.setSamplingRate(new Integer(44100));
audio.setVolume(new Integer(500));
EncodingAttributes attrs = new EncodingAttributes();
attrs.setFormat("wav");
attrs.setAudioAttributes(audio);
attrs.setDuration(duration);
encoder.encode(source, target, attrs);
} catch (IllegalArgumentException e) {
e.printStackTrace();
} catch (InputFormatException e) {
e.printStackTrace();
} catch (EncoderException e) {
e.printStackTrace();
}
}
//计算WAV文件时间
public static long CalculationTime(String adress) throws LineUnavailableException,
UnsupportedAudioFileException, IOException{
File file = new File(adress);
Clip clip = AudioSystem.getClip();
AudioInputStream ais = AudioSystem.getAudioInputStream(file);
clip.open(ais);
long times = (long) (clip.getMicrosecondLength() / 1000000D);
return times;
}
//获取当前时间+给定秒之后的时间
public static String getDateByAdd(long s){
long currentTime = System.currentTimeMillis() ;
currentTime += s;
Date date = new Date(currentTime);
SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
String dateStr = sdf.format(date);
return dateStr ;
}
/**
*
* @Title: compare_date
* @Description: TODO(比较日期大小)
* @param @param DATE1
* @param @param DATE2
* @param @return 参数
* @return int 返回类型
* @throws
*/
public static int compare_date(String DATE1, String DATE2) {
DateFormat df = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
try {
Date dt1 = df.parse(DATE1);
Date dt2 = df.parse(DATE2);
if (dt1.getTime() > dt2.getTime()) {
return 1 ;
} else if (dt1.getTime() < dt2.getTime()) {
return -1 ;
} else {
return 0;
}
} catch (Exception exception) {
exception.printStackTrace();
}
return 0;
}
/**
*
* @Title: getNowTime
* @Description: TODO(获取当前时间)
* @param @return 参数
* @return String 返回类型
* @throws
*/
public static String getNowTime(){
SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
String now = sdf.format(new Date()) ;
return now ;
}
public static void main(String[] args) throws ParseException {
DateFormat df = new SimpleDateFormat("yyyy-MM-dd hh:mm");
Date dt1 = df.parse(null);
System.out.println(dt1.getTime() );
}
}
jave 语音格式转换jar下载