Commit 3c49197fc5b47858d025957f879cd058af3f8deb

Authored by 王通
1 parent e9257718

1.报站语音合成代码合并(lggj)

2.设备管理权限控制
3.站点加入公司分公司加权限控制
4.视频播放调整(多sim情况处理)
... ... @@ -433,7 +433,25 @@
433 433 <artifactId>kotlin-stdlib</artifactId>
434 434 <version>1.3.72</version>
435 435 </dependency>
436   - </dependencies>
  436 +
  437 + <dependency>
  438 + <groupId>com.squareup.okhttp3</groupId>
  439 + <artifactId>okhttp</artifactId>
  440 + <version>4.10.0</version>
  441 + </dependency>
  442 +
  443 + <dependency>
  444 + <groupId>org.java-websocket</groupId>
  445 + <artifactId>Java-WebSocket</artifactId>
  446 + <version>1.5.3</version>
  447 + </dependency>
  448 +
  449 + <dependency>
  450 + <groupId>org.bytedeco</groupId>
  451 + <artifactId>javacv-platform</artifactId>
  452 + <version>1.5.11</version>
  453 + </dependency>
  454 + </dependencies>
437 455  
438 456 <dependencyManagement>
439 457 <dependencies>
... ...
src/main/java/com/bsth/controller/gps/GpsController.java
1 1 package com.bsth.controller.gps;
2 2  
  3 +import com.bsth.common.Constants;
3 4 import com.bsth.data.BasicData;
4 5 import com.bsth.data.gpsdata_v2.GpsRealData;
5 6 import com.bsth.data.gpsdata_v2.entity.GpsEntity;
... ... @@ -7,13 +8,16 @@ import com.bsth.data.gpsdata_v2.handlers.overspeed.GpsOverspeed;
7 8 import com.bsth.data.gpsdata_v2.handlers.overspeed.OverspeedProcess;
8 9 import com.bsth.data.schedule.e_state_check.ScheduleStationCodeChecker;
9 10 import com.bsth.data.schedule.e_state_check.entity.SCodeInfo;
  11 +import com.bsth.entity.sys.CompanyAuthority;
10 12 import com.bsth.service.gps.GpsService;
11 13 import com.bsth.service.gps.entity.GpsSpeed;
12 14 import com.google.common.base.Splitter;
13 15 import org.springframework.beans.factory.annotation.Autowired;
14 16 import org.springframework.web.bind.annotation.*;
15 17  
  18 +import javax.servlet.http.HttpServletRequest;
16 19 import javax.servlet.http.HttpServletResponse;
  20 +import javax.servlet.http.HttpSession;
17 21 import java.text.ParseException;
18 22 import java.util.ArrayList;
19 23 import java.util.HashMap;
... ... @@ -38,10 +42,11 @@ public class GpsController {
38 42 @RequestParam(defaultValue = "0") int page,
39 43 @RequestParam(defaultValue = "15") int size,
40 44 @RequestParam(defaultValue = "timestamp") String order,
41   - @RequestParam(defaultValue = "DESC") String direction) {
  45 + @RequestParam(defaultValue = "DESC") String direction, HttpServletRequest request) {
42 46  
43   -
44   - return gpsService.search(map, page, size, order, direction);
  47 + HttpSession session = request.getSession();
  48 + List<CompanyAuthority> cmyAuths = (List<CompanyAuthority>) session.getAttribute(Constants.COMPANY_AUTHORITYS);
  49 + return gpsService.search(map, page, size, order, direction, cmyAuths);
45 50 }
46 51  
47 52 @RequestMapping(value = "/real/line/{lineCode}")
... ...
src/main/java/com/bsth/data/BasicData.java
... ... @@ -14,6 +14,7 @@ import java.util.Set;
14 14  
15 15 import com.bsth.entity.*;
16 16 import com.bsth.repository.*;
  17 +import com.bsth.util.db.DBUtils_MS;
17 18 import org.apache.commons.lang3.StringUtils;
18 19 import org.slf4j.Logger;
19 20 import org.slf4j.LoggerFactory;
... ... @@ -62,6 +63,9 @@ public class BasicData {
62 63 //车辆自编号和sim号对照 (K:车辆自编号 V: sim号)
63 64 public static Map<String, String> nbbm2SimMap;
64 65  
  66 + //车辆自编号和sim号对照 (K:车辆自编号 V: sim号)
  67 + public static Map<String, String> nbbm2Sim2Map;
  68 +
65 69 //站点编码和名称对照,包括停车场 (K: lineCode_updown_stationCode ,V:站点名称)
66 70 public static Map<String, String> stationCode2NameMap;
67 71  
... ... @@ -105,6 +109,8 @@ public class BasicData {
105 109 // 线路编码_日期 等级
106 110 public static Map<String, String> lineDate2Level;
107 111  
  112 + private static JdbcTemplate msJdbcTemplate = new JdbcTemplate(DBUtils_MS.getDataSource());
  113 +
108 114 static Logger logger = LoggerFactory.getLogger(BasicData.class);
109 115  
110 116 public static String getStationNameByCode(String code, String prefix){
... ... @@ -238,8 +244,10 @@ public class BasicData {
238 244 Map<String, String> nbbmCompanyPlate = new HashMap<>();
239 245 // 车辆自编号和sim对照
240 246 Map<String, String> nbbm2Sim = new HashMap<>();
  247 + Map<String, String> nbbm2Sim2 = new HashMap<>();
241 248  
242 249 Iterator<Cars> carIterator = carsRepository.findAll().iterator();
  250 + List<Map<String, Object>> maps = msJdbcTemplate.queryForList("SELECT in_code, sim, relation_sim FROM bsth_c_device_sim_mapping");
243 251 Cars car;
244 252 while (carIterator.hasNext()) {
245 253 car = carIterator.next();
... ... @@ -247,7 +255,11 @@ public class BasicData {
247 255 nbbm2CompanyCode.put(car.getInsideCode(), car.getBusinessCode());
248 256 nbbm2FgsCompanyCode.put(car.getInsideCode(), car.getBrancheCompanyCode() + "_" + car.getBusinessCode() );
249 257 nbbmCompanyPlate.put(car.getInsideCode(), car.getCarPlate());
250   - nbbm2Sim.put(car.getInsideCode(), car.getSim());
  258 + }
  259 + for (Map<String, Object> map : maps) {
  260 + String inCode = (String) map.get("in_code"), sim = (String) map.get("sim"), sim2 = (String) map.get("relation_sim");
  261 + nbbm2Sim.put(inCode, sim);
  262 + nbbm2Sim2.put(inCode, sim2);
251 263 }
252 264  
253 265 deviceId2NbbmMap = deviceId2Nbbm;
... ... @@ -255,6 +267,7 @@ public class BasicData {
255 267 nbbm2FgsCompanyCodeMap = nbbm2FgsCompanyCode;
256 268 nbbmCompanyPlateMap = nbbmCompanyPlate;
257 269 nbbm2SimMap = nbbm2Sim;
  270 + nbbm2Sim2Map = nbbm2Sim2;
258 271 }
259 272  
260 273 /**
... ...
src/main/java/com/bsth/data/gpsdata_v2/entity/GpsEntity.java
... ... @@ -129,6 +129,11 @@ public class GpsEntity implements Cloneable{
129 129 private String sim;
130 130  
131 131 /**
  132 + * sim号 拓华有两套设备
  133 + */
  134 + private String sim2;
  135 +
  136 + /**
132 137 * 当前乘客数
133 138 */
134 139 private int passengerNum;
... ... @@ -450,6 +455,14 @@ public class GpsEntity implements Cloneable{
450 455 this.sim = sim;
451 456 }
452 457  
  458 + public String getSim2() {
  459 + return sim2;
  460 + }
  461 +
  462 + public void setSim2(String sim2) {
  463 + this.sim2 = sim2;
  464 + }
  465 +
453 466 public int getPassengerNum() {
454 467 return passengerNum;
455 468 }
... ...
src/main/java/com/bsth/data/gpsdata_v2/load/GatewayHttpLoader.java
... ... @@ -71,7 +71,7 @@ public class GatewayHttpLoader implements ApplicationContextAware, InitializingB
71 71 list = GpsDataUtils.clearInvalid(list);
72 72  
73 73 List<GpsEntity> ups = new ArrayList<>();
74   - String nbbm, sim;
  74 + String nbbm, sim, sim2;
75 75 for (GpsEntity gps : list) {
76 76 if (StringUtils.isBlank(gps.getDeviceId()))
77 77 continue;
... ... @@ -82,7 +82,9 @@ public class GatewayHttpLoader implements ApplicationContextAware, InitializingB
82 82 nbbm = BasicData.deviceId2NbbmMap.get(gps.getDeviceId());
83 83 if (!StringUtils.isBlank(nbbm)) {
84 84 sim = BasicData.nbbm2SimMap.get(nbbm);
  85 + sim2 = BasicData.nbbm2Sim2Map.get(nbbm);
85 86 gps.setSim(sim);
  87 + gps.setSim2(sim2);
86 88 }
87 89 gps.setNbbm(nbbm);
88 90 ups.add(gps);
... ...
src/main/java/com/bsth/data/schedule/DayOfSchedule.java
... ... @@ -366,6 +366,9 @@ public class DayOfSchedule {
366 366 sch.setScheduleDateStr(fmtyyyyMMdd.print(sch.getScheduleDate().getTime()));
367 367 sch.setRealExecDate(sch.getScheduleDateStr());
368 368 sch.setCreateDate(d);
  369 + if (sch.getStatus() == null) {
  370 + sch.setStatus(0);
  371 + }
369 372  
370 373 if (StringUtils.isEmpty(sch.getFcsj()))
371 374 sch.setFcsj("00:00");
... ...
src/main/java/com/bsth/entity/Station.java
... ... @@ -5,6 +5,7 @@ import com.fasterxml.jackson.annotation.JsonIgnoreProperties;
5 5 import org.geolatte.geom.Point;
6 6 import org.hibernate.annotations.DynamicInsert;
7 7 import org.hibernate.annotations.DynamicUpdate;
  8 +import org.hibernate.annotations.Formula;
8 9  
9 10 import javax.persistence.*;
10 11 import java.util.Date;
... ... @@ -130,6 +131,20 @@ public class Station {
130 131  
131 132 private String standardStationCode;
132 133  
  134 + private String company;
  135 +
  136 + @Transient
  137 + private String companyName;
  138 +
  139 + private String brancheCompany;
  140 +
  141 + @Transient
  142 + private String brancheCompanyName;
  143 +
  144 + /** 组合公司分公司编码 */
  145 + @Formula(" concat(company, '_', branche_company) ")
  146 + private String cgsbm;
  147 +
133 148 public Integer getId() {
134 149 return id;
135 150 }
... ... @@ -321,4 +336,44 @@ public class Station {
321 336 public void setStandardStationCode(String standardStationCode) {
322 337 this.standardStationCode = standardStationCode;
323 338 }
  339 +
  340 + public String getCompany() {
  341 + return company;
  342 + }
  343 +
  344 + public void setCompany(String company) {
  345 + this.company = company;
  346 + }
  347 +
  348 + public String getCompanyName() {
  349 + return companyName;
  350 + }
  351 +
  352 + public void setCompanyName(String companyName) {
  353 + this.companyName = companyName;
  354 + }
  355 +
  356 + public String getBrancheCompany() {
  357 + return brancheCompany;
  358 + }
  359 +
  360 + public void setBrancheCompany(String brancheCompany) {
  361 + this.brancheCompany = brancheCompany;
  362 + }
  363 +
  364 + public String getBrancheCompanyName() {
  365 + return brancheCompanyName;
  366 + }
  367 +
  368 + public void setBrancheCompanyName(String brancheCompanyName) {
  369 + this.brancheCompanyName = brancheCompanyName;
  370 + }
  371 +
  372 + public String getCgsbm() {
  373 + return cgsbm;
  374 + }
  375 +
  376 + public void setCgsbm(String cgsbm) {
  377 + this.cgsbm = cgsbm;
  378 + }
324 379 }
... ...
src/main/java/com/bsth/entity/realcontrol/ScheduleRealInfo.java
... ... @@ -137,7 +137,7 @@ public class ScheduleRealInfo {
137 137 private Long zdsjActualTime;
138 138  
139 139 /**班次状态 0 未执行 1 正在执行 2 已执行 -1 已烂班 */
140   - private int status;
  140 + private Integer status;
141 141  
142 142 private String adjustExps;
143 143  
... ... @@ -617,11 +617,11 @@ public class ScheduleRealInfo {
617 617 this.zdsjActualTime = zdsjActualTime;
618 618 }
619 619  
620   - public int getStatus() {
  620 + public Integer getStatus() {
621 621 return status;
622 622 }
623 623  
624   - public void setStatus(int status) {
  624 + public void setStatus(Integer status) {
625 625 this.status = status;
626 626 }
627 627  
... ...
src/main/java/com/bsth/entity/speech/SpeechRequest.java 0 → 100644
  1 +package com.bsth.entity.speech;
  2 +
  3 +import com.fasterxml.jackson.annotation.JsonIgnore;
  4 +
  5 +import java.util.HashMap;
  6 +import java.util.Map;
  7 +
  8 +public class SpeechRequest {
  9 +
  10 + /**
  11 + * 包含appid
  12 + */
  13 + private Map<String, Object> common = new HashMap<>();
  14 +
  15 + /**
  16 + * 音频合成参数
  17 + */
  18 + private Map<String, Object> business = new HashMap<>();
  19 +
  20 + /**
  21 + * 数据、状态参数
  22 + */
  23 + private Map<String, Object> data = new HashMap<>();
  24 +
  25 + @JsonIgnore
  26 + private boolean completed = false;
  27 +
  28 + public Map<String, Object> getCommon() {
  29 + return common;
  30 + }
  31 +
  32 + public void setCommon(Map<String, Object> common) {
  33 + this.common = common;
  34 + }
  35 +
  36 + public Map<String, Object> getBusiness() {
  37 + return business;
  38 + }
  39 +
  40 + public void setBusiness(Map<String, Object> business) {
  41 + this.business = business;
  42 + }
  43 +
  44 + public Map<String, Object> getData() {
  45 + return data;
  46 + }
  47 +
  48 + public void setData(Map<String, Object> data) {
  49 + this.data = data;
  50 + }
  51 +
  52 + public boolean isCompleted() {
  53 + return completed;
  54 + }
  55 +
  56 + public void setCompleted(boolean completed) {
  57 + this.completed = completed;
  58 + }
  59 +}
... ...
src/main/java/com/bsth/entity/speech/SpeechResponse.java 0 → 100644
  1 +package com.bsth.entity.speech;
  2 +
  3 +/**
  4 + * 讯飞在线语音合成返回json
  5 + */
  6 +public class SpeechResponse {
  7 +
  8 + private int code;
  9 +
  10 + private String message;
  11 +
  12 + private String sid;
  13 +
  14 + private AudioData data;
  15 +
  16 + public int getCode() {
  17 + return code;
  18 + }
  19 +
  20 + public void setCode(int code) {
  21 + this.code = code;
  22 + }
  23 +
  24 + public String getMessage() {
  25 + return message;
  26 + }
  27 +
  28 + public void setMessage(String message) {
  29 + this.message = message;
  30 + }
  31 +
  32 + public String getSid() {
  33 + return sid;
  34 + }
  35 +
  36 + public void setSid(String sid) {
  37 + this.sid = sid;
  38 + }
  39 +
  40 + public AudioData getData() {
  41 + return data;
  42 + }
  43 +
  44 + public void setData(AudioData data) {
  45 + this.data = data;
  46 + }
  47 +
  48 + public final static class AudioData {
  49 +
  50 + private String audio;
  51 +
  52 + private String ced;
  53 +
  54 + private int status;
  55 +
  56 + public String getAudio() {
  57 + return audio;
  58 + }
  59 +
  60 + public void setAudio(String audio) {
  61 + this.audio = audio;
  62 + }
  63 +
  64 + public String getCed() {
  65 + return ced;
  66 + }
  67 +
  68 + public void setCed(String ced) {
  69 + this.ced = ced;
  70 + }
  71 +
  72 + public int getStatus() {
  73 + return status;
  74 + }
  75 +
  76 + public void setStatus(int status) {
  77 + this.status = status;
  78 + }
  79 +
  80 + @Override
  81 + public String toString() {
  82 + return "AudioData{" +
  83 + "audio='" + audio + '\'' +
  84 + ", ced='" + ced + '\'' +
  85 + ", status=" + status +
  86 + '}';
  87 + }
  88 + }
  89 +
  90 + @Override
  91 + public String toString() {
  92 + return "SpeechResponse{" +
  93 + "code=" + code +
  94 + ", message='" + message + '\'' +
  95 + ", sid='" + sid + '\'' +
  96 + ", audioData=" + data +
  97 + '}';
  98 + }
  99 +}
... ...
src/main/java/com/bsth/service/gps/GpsService.java
1 1 package com.bsth.service.gps;
2 2  
  3 +import com.bsth.entity.sys.CompanyAuthority;
3 4 import com.bsth.service.gps.entity.GpsOutbound_DTO;
4 5 import com.bsth.service.gps.entity.GpsSpeed;
5 6 import com.bsth.service.gps.entity.GpsSpeed_DTO;
... ... @@ -17,7 +18,7 @@ public interface GpsService {
17 18  
18 19 Map<String, Object> findBuffAeraByCode(String lineCode, String code, String type);
19 20  
20   - Map<String, Object> search(Map<String, Object> map, int page, int size, String order, String direction);
  21 + Map<String, Object> search(Map<String, Object> map, int page, int size, String order, String direction, List<CompanyAuthority> cmyAuths);
21 22  
22 23 Map<String,Object> removeRealGps(String device);
23 24  
... ...
src/main/java/com/bsth/service/gps/GpsServiceImpl.java
... ... @@ -28,6 +28,9 @@ import java.util.Set;
28 28  
29 29 import javax.servlet.http.HttpServletResponse;
30 30  
  31 +import com.bsth.entity.sys.CompanyAuthority;
  32 +import com.bsth.entity.sys.SysUser;
  33 +import com.bsth.security.util.SecurityUtils;
31 34 import org.apache.commons.lang3.StringUtils;
32 35 import org.apache.poi.hssf.usermodel.HSSFCellStyle;
33 36 import org.apache.poi.hssf.usermodel.HSSFWorkbook;
... ... @@ -644,9 +647,13 @@ public class GpsServiceImpl implements GpsService {
644 647 }
645 648  
646 649 @Override
647   - public Map<String, Object> search(Map<String, Object> map, int page, int size, String order, String direction) {
  650 + public Map<String, Object> search(Map<String, Object> map, int page, int size, String order, String direction, List<CompanyAuthority> cmyAuths) {
648 651 Map<String, Object> rsMap = new HashMap<>();
  652 + Set<String> codes = new HashSet<>();
649 653 try {
  654 + for (CompanyAuthority ca : cmyAuths) {
  655 + codes.add(ca.getCompanyCode());
  656 + }
650 657 //全量
651 658 List<GpsEntity> list = new ArrayList<>(gpsRealData.all());
652 659 //过滤后的
... ... @@ -661,7 +668,8 @@ public class GpsServiceImpl implements GpsService {
661 668 }
662 669 //过滤数据
663 670 for (GpsEntity gps : list) {
664   - if (fieldEquals(fs, gps, map))
  671 + String companyCode = BasicData.nbbm2CompanyCodeMap.get(gps.getNbbm());
  672 + if (codes.contains(companyCode) && fieldEquals(fs, gps, map))
665 673 rs.add(gps);
666 674 }
667 675  
... ...
src/main/java/com/bsth/service/impl/StationRouteServiceImpl.java
... ... @@ -5,27 +5,25 @@ import com.bsth.entity.*;
5 5 import com.bsth.entity.search.CustomerSpecs;
6 6 import com.bsth.repository.*;
7 7 import com.bsth.service.StationRouteService;
8   -import com.bsth.util.CoordinateConverter;
9   -import com.bsth.util.ExcelUtil;
10   -import com.bsth.util.FTPClientUtils;
  8 +import com.bsth.util.*;
11 9 import com.bsth.util.Geo.GeoUtils;
12 10 import com.bsth.util.Geo.Point;
13   -import com.bsth.util.PackTarGZUtils;
14 11 import com.bsth.util.db.DBUtils_MS;
15 12 import com.google.common.base.Splitter;
16 13 import org.apache.commons.lang3.StringUtils;
17 14 import org.geolatte.geom.Polygon;
18 15 import org.springframework.beans.factory.annotation.Autowired;
  16 +import org.springframework.beans.factory.annotation.Value;
19 17 import org.springframework.data.domain.Sort;
20 18 import org.springframework.data.domain.Sort.Direction;
21 19 import org.springframework.stereotype.Service;
22 20  
23 21 import javax.servlet.http.HttpServletResponse;
24   -import java.io.ByteArrayInputStream;
25   -import java.io.File;
26   -import java.io.InputStream;
  22 +import java.io.*;
27 23 import java.text.DecimalFormat;
28 24 import java.util.*;
  25 +import java.util.zip.ZipEntry;
  26 +import java.util.zip.ZipOutputStream;
29 27  
30 28 /**
31 29 *
... ... @@ -44,7 +42,13 @@ import java.util.*;
44 42 */
45 43  
46 44 @Service
47   -public class StationRouteServiceImpl extends BaseServiceImpl<StationRoute, Integer> implements StationRouteService{
  45 +public class StationRouteServiceImpl extends BaseServiceImpl<StationRoute, Integer> implements StationRouteService {
  46 +
  47 + @Value("${path.speech.common}")
  48 + private String commonPath;
  49 +
  50 + @Value("${path.speech.line}")
  51 + private String linePathPattern;
48 52  
49 53 @Autowired
50 54 private StationRouteRepository stationRouteRepository;
... ... @@ -422,6 +426,12 @@ public class StationRouteServiceImpl extends BaseServiceImpl&lt;StationRoute, Integ
422 426 /** 查询线路信息下的站点路由信息 @param:<lineId:线路ID> */
423 427 List<Object[]> objects = stationRouteRepository.usingSingle(lineId);
424 428 if (objects.size()>0) {
  429 + // 报站音频
  430 + Set<String> languages = new HashSet<>();
  431 + languages.add("cn");
  432 + //languages.add("sh");
  433 + //languages.add("en");
  434 + InputStream tts = ttsAndZip(objects, line, languages);
425 435 /** 获取配置文件里的ftp登录参数 */
426 436 Map<String, Object> FTPParamMap = readPropertiesGetFTPParam();
427 437 // 压缩文件名
... ... @@ -490,6 +500,8 @@ public class StationRouteServiceImpl extends BaseServiceImpl&lt;StationRoute, Integ
490 500  
491 501 // textFile.delete();
492 502  
  503 + clientUtils.deleteFtpFile(url, port, username, password, remotePath + "/voice/", String.format("%s.zip", line.getLineCode()));
  504 + clientUtils.uploadFile(url, port, username, password, remotePath + "/voice/", String.format("%s.zip", line.getLineCode()), tts);
493 505  
494 506 resultMap.put("status", ResponseCode.SUCCESS);
495 507 }else {
... ... @@ -1001,4 +1013,266 @@ public class StationRouteServiceImpl extends BaseServiceImpl&lt;StationRoute, Integ
1001 1013 }
1002 1014 }
1003 1015 }
  1016 +
  1017 + private String subLine2Ftp(LineRegion lineRegion) {
  1018 + StringBuilder builder = new StringBuilder();
  1019 + int len = lineRegion.getStationRoutes().size();
  1020 + int idx = 1;
  1021 + for (int i = 0;i < len;i++) {
  1022 + LsStationRoute route = lineRegion.getStationRoutes().get(i);
  1023 + builder.append(route.getCenterPointWgs().getPosition().getCoordinate(0))
  1024 + .append("\t").append(route.getCenterPointWgs().getPosition().getCoordinate(1))
  1025 + .append("\t").append(i == len - 1 ? 2 : 1)
  1026 + .append("\t").append(idx).append("\t");
  1027 + for (int j = 0;j < 8 - route.getStationCode().length();j++) {
  1028 + builder.append("0");
  1029 + }
  1030 + builder.append(route.getStationCode())
  1031 + .append("\t").append((int) route.getDistances().doubleValue() * 1000)
  1032 + .append("\t0")
  1033 + .append("\t").append(route.getStationName())
  1034 + .append("\t").append(route.getStationNameEn())
  1035 + .append("\r\n");
  1036 +
  1037 + idx++;
  1038 + }
  1039 +
  1040 + return builder.toString();
  1041 + }
  1042 +
  1043 + /**
  1044 + * tts合成及打包
  1045 + * @param objects
  1046 + * @param line
  1047 + * @param languages 语言 如:cn、en、sh
  1048 + */
  1049 + private InputStream ttsAndZip(List<Object[]> objects, Line line, Set<String> languages) throws Exception {
  1050 + String lineId = line.getLineCode();
  1051 + StringBuilder cnBuilder = new StringBuilder(line.getName()).append("[p1000]"), enBuilder = new StringBuilder("Hello[p1000]");
  1052 + int ups = 0, downs = 0;
  1053 + for (int i = 0;i < objects.size();i++) {
  1054 + Object[] objArr = objects.get(i);
  1055 + int direction = (int) objArr[8];
  1056 + String stationName = objArr[7] == null ? null : objArr[7].toString(), stationNameEn = objArr[9] == null ? null : objArr[9].toString();
  1057 + if (StringUtils.isEmpty(stationName)) {
  1058 + throw new RuntimeException("存在异常的中文站点名称");
  1059 + }
  1060 + // 如果要生成英语报站语音
  1061 + if (languages.contains("en")) {
  1062 + if (StringUtils.isEmpty(stationNameEn)) {
  1063 + throw new RuntimeException("存在异常的英文站点名称");
  1064 + }
  1065 + enBuilder.append(stationNameEn).append("[p1000]");
  1066 + }
  1067 + cnBuilder.append(stationName).append("[p1000]");
  1068 + if (direction == 0) {
  1069 + ups++;
  1070 + } else if (direction == 1) {
  1071 + // 环线
  1072 + if (line.getLinePlayType() == 1) {
  1073 + break;
  1074 + }
  1075 + downs++;
  1076 + }
  1077 + }
  1078 + cnBuilder.delete(cnBuilder.length() - 8, cnBuilder.length() - 1);
  1079 + enBuilder.delete(enBuilder.length() - 8, enBuilder.length() - 1);
  1080 +
  1081 + // 文本转语音并进行分割
  1082 + // 音频存放及压缩文件路径
  1083 + String linePath = String.format(linePathPattern, lineId), voicePath = String.format("%s%s.zip", linePath, lineId);
  1084 + try {
  1085 + String path = String.format("%scn.mp3", linePath);
  1086 + IFlyUtils.textToSpeechCn(cnBuilder.toString(), path);
  1087 + AudioOperationUtils.splitBySilence(path, String.format("%scn", linePath), 500, -40);
  1088 + } catch (Exception e) {
  1089 + throw new RuntimeException(e);
  1090 + }
  1091 + if (languages.contains("sh")) {
  1092 + try {
  1093 + String path = String.format("%ssh.mp3", linePath);
  1094 + IFlyUtils.textToSpeechSh(cnBuilder.toString(), path);
  1095 + AudioOperationUtils.splitBySilence(path, String.format("%ssh", linePath), 500, -40);
  1096 + } catch (Exception e) {
  1097 + throw new RuntimeException(e);
  1098 + }
  1099 + }
  1100 + if (languages.contains("en")) {
  1101 + try {
  1102 + String path = String.format("%sen.mp3", linePath);
  1103 + IFlyUtils.textToSpeechEn(enBuilder.toString(), path);
  1104 + AudioOperationUtils.splitBySilence(path, String.format("%sen", linePath), 500, -40);
  1105 + } catch (Exception e) {
  1106 + throw new RuntimeException(e);
  1107 + }
  1108 + }
  1109 + // 删除原线路音频
  1110 + File file = new File(linePath);
  1111 + for (File f : file.listFiles()) {
  1112 + if (f.isFile() && f.getName().endsWith(".mp3")) {
  1113 + file.delete();
  1114 + }
  1115 + }
  1116 +
  1117 + // 合并每站起步、到达语音
  1118 + int seq = 1, startSeq = 1, direction = 0;
  1119 + seq = merge(lineId, seq, startSeq, direction, ups, languages);
  1120 + startSeq = ups + 1;
  1121 + direction = 1;
  1122 + merge(lineId, seq, startSeq, direction, ups + downs, languages);
  1123 +
  1124 + // 压缩音频到zip
  1125 + ZipOutputStream zos = new ZipOutputStream(new FileOutputStream(voicePath));
  1126 + for (File f : file.listFiles()) {
  1127 + if (f.isFile() && f.getName().endsWith(".mp3")) {
  1128 + addFileToZip(zos, f);
  1129 + }
  1130 + }
  1131 + // Key打头音频
  1132 + file = new File(commonPath);
  1133 + for (File f : file.listFiles()) {
  1134 + if (f.isFile() && f.getName().startsWith("Key-")) {
  1135 + addFileToZip(zos, f);
  1136 + }
  1137 + }
  1138 + zos.flush();
  1139 + zos.close();
  1140 +
  1141 + return new FileInputStream(voicePath);
  1142 + }
  1143 +
  1144 + private static void addFileToZip(ZipOutputStream zos, File file) throws IOException {
  1145 + FileInputStream fis = new FileInputStream(file);
  1146 + ZipEntry zipEntry = new ZipEntry(file.getName());
  1147 + zos.putNextEntry(zipEntry);
  1148 +
  1149 + byte[] bytes = new byte[4096];
  1150 + int length;
  1151 + while ((length = fis.read(bytes)) >= 0) {
  1152 + zos.write(bytes, 0, length);
  1153 + }
  1154 +
  1155 + zos.closeEntry();
  1156 + fis.close();
  1157 + }
  1158 +
  1159 + private int merge(String lineId, int seq, int startSeq, int direction, int terminal, Set<String> languages) throws Exception {
  1160 + for (int i = startSeq;i <= terminal;i++) {
  1161 + if (i > startSeq) {
  1162 + if (i == startSeq + 1) {
  1163 + // 生成首站
  1164 + mergeOriginStart(lineId, seq, i, direction, terminal, languages);
  1165 + mergeNormalArrive(lineId, seq, i, direction, terminal, languages);
  1166 + } else if (i == terminal) {
  1167 + // 生成终点站
  1168 + mergeNormalStart(lineId, seq, i, direction, terminal, languages);
  1169 + mergeTerminalArrive(lineId, seq, i, direction, terminal, languages);
  1170 + } else {
  1171 + // 生成中途站
  1172 + mergeNormalStart(lineId, seq, i, direction, terminal, languages);
  1173 + mergeNormalArrive(lineId, seq, i, direction, terminal, languages);
  1174 + }
  1175 + seq++;
  1176 + }
  1177 + }
  1178 +
  1179 + return seq;
  1180 + }
  1181 +
  1182 + private void mergeOriginStart(String lineId, int seq, int stationLevel, int direction, int terminal, Set<String> languages) throws Exception {
  1183 + String linePath = String.format(linePathPattern, lineId);
  1184 + List<String> arr = Arrays.asList(commonPath + "cn_origin_1.mp3", linePath + String.format("cn/%03d.mp3", 0), commonPath + "cn_origin_2.mp3", linePath + String.format("cn/%03d.mp3", terminal), commonPath + "sh_origin_1.mp3", linePath + String.format("sh/%03d.mp3", 0), commonPath + "sh_origin_2.mp3", linePath + String.format("cn/%03d.mp3", terminal), commonPath + "cn_start_1.mp3", linePath + String.format("cn/%03d.mp3", stationLevel), commonPath + "cn_start_2.mp3", commonPath + "sh_start_1.mp3", linePath + String.format("sh/%03d.mp3", stationLevel), commonPath + "sh_start_2.mp3", commonPath + "en_1.mp3", linePath + String.format("en/%03d.mp3", stationLevel), commonPath + "cn_start_3.mp3", commonPath + "sh_start_3.mp3");
  1185 + List<String> inputPaths = new ArrayList<>();
  1186 + for (String path : arr) {
  1187 + for (String lang : languages) {
  1188 + if (path.indexOf(lang) > -1) {
  1189 + inputPaths.add(path);
  1190 + break;
  1191 + }
  1192 + }
  1193 + }
  1194 + AudioOperationUtils.merge(inputPaths, String.format("%s%03da%s-%03d-%s-Start.mp3", linePath, seq, direction == 0 ? "u" : "d", direction == 0 ? stationLevel : terminal - stationLevel + 1, direction == 0 ? "Up" : "Dn"));
  1195 + }
  1196 +
  1197 + private void mergeNormalStart(String lineId, int seq, int stationLevel, int direction, int terminal, Set<String> languages) throws Exception {
  1198 + String linePath = String.format(linePathPattern, lineId);
  1199 + List<String> arr = Arrays.asList(commonPath + "cn_start.mp3", linePath + String.format("cn/%03d.mp3", stationLevel), commonPath + "cn_start_2.mp3", commonPath + "sh_start_1.mp3", linePath + String.format("sh/%03d.mp3", stationLevel), commonPath + "sh_start_2.mp3", commonPath + "en_1.mp3", linePath + String.format("en/%03d.mp3", stationLevel), commonPath + "cn_start_3.mp3", commonPath + "sh_start_3.mp3");
  1200 + List<String> inputPaths = new ArrayList<>();
  1201 + for (String path : arr) {
  1202 + for (String lang : languages) {
  1203 + if (path.indexOf(lang) > -1) {
  1204 + inputPaths.add(path);
  1205 + break;
  1206 + }
  1207 + }
  1208 + }
  1209 + AudioOperationUtils.merge(inputPaths, String.format("%s%03da%s-%03d-%s-Start.mp3", linePath, seq, direction == 0 ? "u" : "d", direction == 0 ? stationLevel : terminal - stationLevel + 1, direction == 0 ? "Up" : "Dn"));
  1210 + }
  1211 +
  1212 + private void mergeNormalArrive(String lineId, int seq, int stationLevel, int direction, int terminal, Set<String> languages) throws Exception {
  1213 + String linePath = String.format(linePathPattern, lineId);
  1214 + List<String> arr = new ArrayList<>(Arrays.asList(commonPath + "cn_arrive.mp3", linePath + String.format("cn/%03d.mp3", stationLevel), commonPath + "cn_arrive_1.mp3", linePath + String.format("sh/%03d.mp3", stationLevel), commonPath + "sh_arrive_1.mp3", commonPath + "en_2.mp3", linePath + String.format("en/%03d.mp3", stationLevel)));
  1215 + List<String> inputPaths = new ArrayList<>();
  1216 + if (languages.contains("sh")) {
  1217 + for (int i = 0;i < 3;i++) {
  1218 + arr.add(linePath + String.format("cn/%03d.mp3", 0));
  1219 + arr.add(commonPath + "cn_origin_2.mp3");
  1220 + arr.add(linePath + String.format("cn/%03d.mp3", terminal));
  1221 + arr.add(linePath + String.format("sh/%03d.mp3", 0));
  1222 + arr.add(commonPath + "sh_origin_2.mp3");
  1223 + arr.add(linePath + String.format("sh/%03d.mp3", terminal));
  1224 + }
  1225 + } else {
  1226 + arr.add(linePath + String.format("cn/%03d.mp3", 0));
  1227 + arr.add(commonPath + "cn_origin_2.mp3");
  1228 + arr.add(linePath + String.format("cn/%03d.mp3", terminal));
  1229 + }
  1230 + for (String path : arr) {
  1231 + for (String lang : languages) {
  1232 + if (path.indexOf(lang) > -1) {
  1233 + inputPaths.add(path);
  1234 + break;
  1235 + }
  1236 + }
  1237 + }
  1238 + AudioOperationUtils.merge(inputPaths, String.format("%s%03db%s-%03d-%s-Arrive.mp3", linePath, seq, direction == 0 ? "u" : "d", direction == 0 ? stationLevel : terminal - stationLevel + 1, direction == 0 ? "Up" : "Dn"));
  1239 + }
  1240 +
  1241 + private void mergeTerminalArrive(String lineId, int seq, int stationLevel, int direction, int terminal, Set<String> languages) throws Exception {
  1242 + String linePath = String.format(linePathPattern, lineId);
  1243 + List<String> arr = Arrays.asList(commonPath + "cn_terminal.mp3", linePath + String.format("cn/%03d.mp3", stationLevel), commonPath + "cn_arrive_1.mp3", commonPath + "sh_terminal.mp3", linePath + String.format("sh/%03d.mp3", stationLevel), commonPath + "sh_arrive_1.mp3", commonPath + "en_3.mp3", linePath + String.format("en/%03d.mp3", stationLevel), commonPath + "terminal_music.mp3");
  1244 + List<String> inputPaths = new ArrayList<>();
  1245 + for (String path : arr) {
  1246 + for (String lang : languages) {
  1247 + if (path.indexOf(lang) > -1 || path.indexOf("terminal_music") > -1) {
  1248 + inputPaths.add(path);
  1249 + break;
  1250 + }
  1251 + }
  1252 + }
  1253 + AudioOperationUtils.merge(inputPaths, String.format("%s%03db%s-%03d-%s-Arrive.mp3", linePath, seq, direction == 0 ? "u" : "d", direction == 0 ? stationLevel : terminal - stationLevel + 1, direction == 0 ? "Up" : "Dn"));
  1254 + }
  1255 +
  1256 + private void description() {
  1257 + // Next stop is (en_1.mp3)
  1258 + // We are arrival at (en_2.mp3)
  1259 + // We are arrival at the terminal (en_3.mp3)
  1260 + // 叮咚+欢迎乘坐 (cn_origin_1.mp3)
  1261 + // 公交车方向 (cn_origin_2.mp3)
  1262 + // 叮咚+车辆起步请拉好扶手投币后请配合朝里走下一站 (cn_start.mp3)
  1263 + // 下一站 (cn_start_1.mp3)
  1264 + // 请准备从后门下车 (cn_start_2.mp3)
  1265 + // 乘客们请给需要帮助的乘客让个座谢谢 (cn_start_3.mp3)
  1266 + // 叮咚+车辆进站请注意安全 (cn_arrive.mp3)
  1267 + // 到了请配合从后门下车开门请当心 (cn_arrive_1.mp3)
  1268 + // 叮咚+终点站 (cn_terminal.mp3)
  1269 + // 欢迎乘坐(沪) (sh_origin_1.mp3)
  1270 + // 公交车方向(沪) (sh_origin_2.mp3)
  1271 + // 下一站(沪) (sh_start_1.mp3)
  1272 + // 请准备从后门下车 (sh_start_2.mp3)
  1273 + // 乘客们请给需要帮助的乘客让个座谢谢(沪) (sh_start_3.mp3)
  1274 + // 到了请配合从后门下车开门请当心(沪) (sh_arrive_1.mp3)
  1275 + // 终点站(沪) (sh_terminal.mp3)
  1276 + // 终点音乐 (terminal_music.mp3)
  1277 + }
1004 1278 }
... ...
src/main/java/com/bsth/util/AudioOperationUtils.java 0 → 100644
  1 +package com.bsth.util;
  2 +
  3 +
  4 +import org.bytedeco.javacv.FFmpegFrameGrabber;
  5 +import org.bytedeco.javacv.FFmpegFrameRecorder;
  6 +import org.bytedeco.javacv.Frame;
  7 +
  8 +import java.io.*;
  9 +import java.nio.ShortBuffer;
  10 +import java.util.ArrayList;
  11 +import java.util.List;
  12 +
  13 +public class AudioOperationUtils {
  14 + public static void main(String[] args) throws Exception {
  15 +// int duration = 450000;
  16 +// double silenceThreshold = -40; // 声音阈值,可以根据需要调整,单位通常是分贝dB
  17 +// splitBySilence("D:\\tts.mp3", "D:\\88814\\cn", duration, silenceThreshold);
  18 +
  19 + List<String> paths = new ArrayList<>();
  20 + paths.add("D:/speech/803111/cn/000.mp3");
  21 + paths.add("D:/speech/803111/cn/001.mp3");
  22 + merge(paths, "D:/speech/803111/results.mp3");
  23 + }
  24 +
  25 + public static void merge(List<String> inputPaths, String outputPath) throws Exception {
  26 + File file = new File(outputPath);
  27 + if (!file.getParentFile().exists()) {
  28 + file.getParentFile().mkdirs();
  29 + }
  30 + FFmpegFrameRecorder recorder = new FFmpegFrameRecorder(new File(outputPath), 1);
  31 +
  32 + int i = 0;
  33 + Frame frame = null;
  34 + for (String inputPath : inputPaths) {
  35 + FFmpegFrameGrabber grabber = new FFmpegFrameGrabber(inputPath);
  36 + grabber.start();
  37 + if (i == 0) {
  38 + recorder.setAudioCodec(grabber.getAudioCodec());
  39 + recorder.setFrameRate(grabber.getFrameRate());
  40 + recorder.setFormat(grabber.getFormat());
  41 + recorder.start();
  42 + }
  43 + while ((frame = grabber.grabSamples()) != null) {
  44 + recorder.record(frame);
  45 + }
  46 + grabber.stop();
  47 + grabber.close();
  48 + i++;
  49 + }
  50 + recorder.stop();
  51 + recorder.close();
  52 + }
  53 +
  54 + public static void splitBySilence(String inputPath, String outputPath, int duration, double silenceThreshold) throws Exception {
  55 + File file = new File(outputPath);
  56 + if (!file.exists()) {
  57 + file.mkdirs();
  58 + }
  59 + boolean isSilent = false;
  60 + FFmpegFrameGrabber grabber = new FFmpegFrameGrabber(inputPath);
  61 + grabber.start();
  62 + Frame frame = null;
  63 + List<SilenceInfo> silenceInfos = new ArrayList<>();
  64 + long start = 0, end = 0;
  65 + while((frame = grabber.grabSamples()) != null) {
  66 + ShortBuffer buffer = (ShortBuffer) frame.samples[0];
  67 + double energy = 0;
  68 + while (buffer.hasRemaining()) {
  69 + short sample = buffer.get();
  70 + energy += sample * sample;
  71 + }
  72 + energy /= buffer.capacity();
  73 + double db = 20 * Math.log10(Math.sqrt(energy));
  74 + if (db < silenceThreshold) {
  75 + if (!isSilent && start == 0) {
  76 + isSilent = true;
  77 + start = frame.timestamp;
  78 + }
  79 + } else {
  80 + if (start != 0 && frame.timestamp - start >= duration) {
  81 + SilenceInfo info = new SilenceInfo(end, start);
  82 + silenceInfos.add(info);
  83 + end = frame.timestamp;
  84 + }
  85 + isSilent = false;
  86 + start = 0;
  87 + }
  88 + }
  89 + if (silenceInfos.size() > 0) {
  90 + SilenceInfo info = new SilenceInfo(end, grabber.getLengthInTime());
  91 + silenceInfos.add(info);
  92 + }
  93 + grabber.stop();
  94 + grabber.close();
  95 + grabber = new FFmpegFrameGrabber(inputPath);
  96 + grabber.start();
  97 + int idx = 0;
  98 + boolean flag = false;
  99 + FFmpegFrameRecorder recorder = new FFmpegFrameRecorder(new File(String.format("%s%s%03d.mp3", outputPath, File.separator, idx)), 1);
  100 + recorder.setAudioCodec(grabber.getAudioCodec());
  101 + recorder.setFrameRate(grabber.getFrameRate());
  102 + recorder.setFormat(grabber.getFormat());
  103 + recorder.start();
  104 + SilenceInfo info = silenceInfos.get(idx);
  105 + while ((frame = grabber.grabSamples()) != null) {
  106 + if (idx < silenceInfos.size()) {
  107 + if (frame.timestamp >= info.start && frame.timestamp <= info.end) {
  108 + recorder.record(frame);
  109 + flag = false;
  110 + } else {
  111 + if (!flag) {
  112 + flag = true;
  113 + recorder.stop();
  114 + recorder.close();
  115 + idx++;
  116 + info = silenceInfos.get(idx);
  117 + recorder = new FFmpegFrameRecorder(new File(String.format("%s%s%03d.mp3", outputPath, File.separator, idx)), 1);
  118 + recorder.start();
  119 + recorder.setAudioCodec(grabber.getAudioCodec());
  120 + recorder.setFrameRate(grabber.getFrameRate());
  121 + recorder.setFormat(grabber.getFormat());
  122 + }
  123 + }
  124 + }
  125 + }
  126 + if (recorder != null) {
  127 + recorder.stop();
  128 + recorder.close();
  129 + }
  130 + }
  131 +
  132 + public final static class SilenceInfo {
  133 +
  134 + private long start;
  135 +
  136 + private long end;
  137 +
  138 + public SilenceInfo() {}
  139 +
  140 + public SilenceInfo(long start, long end) {
  141 + this.start = start;
  142 + this.end = end;
  143 + }
  144 +
  145 + public long getStart() {
  146 + return start;
  147 + }
  148 +
  149 + public void setStart(long start) {
  150 + this.start = start;
  151 + }
  152 +
  153 + public long getEnd() {
  154 + return end;
  155 + }
  156 +
  157 + public void setEnd(long end) {
  158 + this.end = end;
  159 + }
  160 + }
  161 +}
... ...
src/main/java/com/bsth/util/IFlyUtils.java 0 → 100644
  1 +package com.bsth.util;
  2 +
  3 +import com.bsth.entity.speech.SpeechRequest;
  4 +import com.bsth.entity.speech.SpeechResponse;
  5 +import com.fasterxml.jackson.core.JsonProcessingException;
  6 +import com.fasterxml.jackson.databind.ObjectMapper;
  7 +import org.java_websocket.client.WebSocketClient;
  8 +import org.java_websocket.handshake.ServerHandshake;
  9 +import org.slf4j.Logger;
  10 +import org.slf4j.LoggerFactory;
  11 +
  12 +import javax.crypto.Mac;
  13 +import javax.crypto.spec.SecretKeySpec;
  14 +import java.io.*;
  15 +import java.net.URI;
  16 +import java.net.URL;
  17 +import java.net.URLEncoder;
  18 +import java.nio.charset.StandardCharsets;
  19 +import java.text.SimpleDateFormat;
  20 +import java.util.*;
  21 +
  22 +public class IFlyUtils {
  23 +
  24 + private final static ObjectMapper mapper = new ObjectMapper();
  25 +
  26 + private final static Logger log = LoggerFactory.getLogger(IFlyUtils.class);
  27 +
  28 + private final static String apiKey = "46780e6779b6b1ba93503f24f097b771";
  29 +
  30 + private final static String apiSecret = "ZWFjNzkzMTkzNzI3YmMzMTgwMWUzMWE0";
  31 +
  32 + private final static String appId = "b4b21ad4";
  33 +
  34 + /**
  35 + * 生成普通话语音
  36 + * text以","进行分割
  37 + * @param text
  38 + */
  39 + public static void textToSpeechCn(String text, String outputPath) throws Exception {
  40 + File file = new File(outputPath);
  41 + if (!file.getParentFile().exists()) {
  42 + file.getParentFile().mkdirs();
  43 + }
  44 + String wsUrl = getAuthUrl("https://tts-api.xfyun.cn/v2/tts", apiKey, apiSecret).replace("https://", "wss://");
  45 + SpeechRequest request = new SpeechRequest();
  46 + request.getCommon().put("app_id", appId);
  47 + request.getBusiness().put("aue", "lame");
  48 + request.getBusiness().put("sfl", 1);
  49 + request.getBusiness().put("vcn", "x4_lingxiaoshan_profnews");
  50 + request.getData().put("text", Base64.getEncoder().encodeToString(text.replace(",", "[p1000]").getBytes("GBK")));
  51 + request.getData().put("status", 2);
  52 + websocketWork(wsUrl, request, new FileOutputStream(file));
  53 + while (!request.isCompleted()) {
  54 + Thread.sleep(500);
  55 + }
  56 + }
  57 +
  58 + /**
  59 + * 生成上海话语音
  60 + * text以","进行分割
  61 + * @param text
  62 + */
  63 + public static void textToSpeechSh(String text, String outputPath) throws Exception {
  64 + String wsUrl = getAuthUrl("https://tts-api.xfyun.cn/v2/tts", apiKey, apiSecret).replace("https://", "wss://");
  65 + SpeechRequest request = new SpeechRequest();
  66 + request.getCommon().put("app_id", appId);
  67 + request.getBusiness().put("aue", "lame");
  68 + request.getBusiness().put("sfl", 1);
  69 + request.getBusiness().put("vcn", "x3_ziling");
  70 + request.getData().put("text", Base64.getEncoder().encodeToString(text.replace(",", "[p1000]").getBytes("GBK")));
  71 + request.getData().put("status", 2);
  72 + websocketWork(wsUrl, request, new FileOutputStream(outputPath));
  73 + while (!request.isCompleted()) {
  74 + Thread.sleep(500);
  75 + }
  76 + }
  77 +
  78 + /**
  79 + * 生成英语语音
  80 + * text以","进行分割
  81 + * @param text
  82 + */
  83 + public static void textToSpeechEn(String text, String outputPath) throws Exception {
  84 + String wsUrl = getAuthUrl("https://tts-api.xfyun.cn/v2/tts", apiKey, apiSecret).replace("https://", "wss://");
  85 + SpeechRequest request = new SpeechRequest();
  86 + request.getCommon().put("app_id", appId);
  87 + request.getBusiness().put("aue", "lame");
  88 + request.getBusiness().put("sfl", 1);
  89 + request.getBusiness().put("vcn", "x4_enus_luna_assist");
  90 + request.getData().put("text", Base64.getEncoder().encodeToString(text.replace(",", "[p1000]").getBytes(StandardCharsets.UTF_8)));
  91 + request.getData().put("status", 2);
  92 + websocketWork(wsUrl, request, new FileOutputStream(outputPath));
  93 + while (!request.isCompleted()) {
  94 + Thread.sleep(500);
  95 + }
  96 + }
  97 +
  98 + public static void websocketWork(String wsUrl, SpeechRequest request, OutputStream out) {
  99 + try {
  100 + URI uri = new URI(wsUrl);
  101 + WebSocketClient webSocketClient = new WebSocketClient(uri) {
  102 + @Override
  103 + public void onOpen(ServerHandshake serverHandshake) {
  104 + try {
  105 + this.send(mapper.writeValueAsString(request));
  106 + } catch (JsonProcessingException e) {
  107 + throw new RuntimeException(e);
  108 + }
  109 + }
  110 +
  111 + @Override
  112 + public void onMessage(String text) {
  113 + try {
  114 + SpeechResponse response = mapper.readValue(text, SpeechResponse.class);
  115 + log.info("response: {}", response);
  116 + if (response.getCode() != 0) {
  117 + log.error("在线语音合成发生错误");
  118 + }
  119 + if (response.getData() != null) {
  120 + byte[] bytes = Base64.getDecoder().decode(response.getData().getAudio());
  121 + out.write(bytes);
  122 + out.flush();
  123 + if (response.getData().getStatus() == 2) {
  124 + request.setCompleted(true);
  125 + out.close();
  126 + }
  127 + }
  128 + } catch (IOException e) {
  129 + throw new RuntimeException(e);
  130 + }
  131 + }
  132 +
  133 + @Override
  134 + public void onClose(int i, String s, boolean b) {
  135 + System.out.println("ws链接已关闭,本次请求完成...");
  136 + }
  137 +
  138 + @Override
  139 + public void onError(Exception e) {
  140 + log.error("发生错误", e);
  141 + }
  142 + };
  143 + webSocketClient.connect();
  144 + } catch (Exception e) {
  145 + log.error("", e);
  146 + }
  147 + }
  148 +
  149 + /**
  150 + * 讯飞语音合成鉴权
  151 + * @param hostUrl
  152 + * @param apiKey
  153 + * @param apiSecret
  154 + * @return
  155 + * @throws Exception
  156 + */
  157 + public static String getAuthUrl(String hostUrl, String apiKey, String apiSecret) throws Exception {
  158 + URL url = new URL(hostUrl);
  159 + // 时间
  160 + SimpleDateFormat format = new SimpleDateFormat("EEE, dd MMM yyyy HH:mm:ss z", Locale.US);
  161 + format.setTimeZone(TimeZone.getTimeZone("GMT"));
  162 + String date = format.format(new Date());
  163 + // 拼接
  164 + String preStr = "host: " + url.getHost() + "\n" +
  165 + "date: " + date + "\n" +
  166 + "GET " + url.getPath() + " HTTP/1.1";
  167 + // SHA256加密
  168 + Mac mac = Mac.getInstance("hmacsha256");
  169 + SecretKeySpec spec = new SecretKeySpec(apiSecret.getBytes(StandardCharsets.UTF_8), "hmacsha256");
  170 + mac.init(spec);
  171 + byte[] hexDigits = mac.doFinal(preStr.getBytes(StandardCharsets.UTF_8));
  172 + // Base64加密
  173 + String sha = Base64.getEncoder().encodeToString(hexDigits);
  174 + // 拼接
  175 + String authorization = String.format("api_key=\"%s\", algorithm=\"%s\", headers=\"%s\", signature=\"%s\"", apiKey, "hmac-sha256", "host date request-line", sha);
  176 + StringBuilder sb = new StringBuilder(hostUrl);
  177 + sb.append("?authorization=").append(Base64.getEncoder().encodeToString(authorization.getBytes(StandardCharsets.UTF_8)))
  178 + .append("&date=").append(URLEncoder.encode(date))
  179 + .append("&host=").append(URLEncoder.encode(url.getHost()));
  180 +// // 拼接地址
  181 +// HttpUrl httpUrl = Objects.requireNonNull(HttpUrl.parse("https://" + url.getHost() + url.getPath())).newBuilder().//
  182 +// addQueryParameter("authorization", Base64.getEncoder().encodeToString(authorization.getBytes(StandardCharsets.UTF_8))).//
  183 +// addQueryParameter("date", date).//
  184 +// addQueryParameter("host", url.getHost()).//
  185 +// build();
  186 +
  187 + return sb.toString();
  188 + }
  189 +}
... ...
src/main/resources/application-cloud.properties
... ... @@ -73,4 +73,7 @@ sso.enabled= false
73 73 sso.systemcode = SYS0023
74 74 sso.http.url.login= https://127.0.0.1/portal/index.html#/login
75 75 sso.http.url.logout= https://127.0.0.1/information/api/v1/logout
76   -sso.http.url.auth= https://127.0.0.1/information/authenticate/authorityAuthentication
77 76 \ No newline at end of file
  77 +sso.http.url.auth= https://127.0.0.1/information/authenticate/authorityAuthentication
  78 +
  79 +path.speech.common = /data/control/speech/common/
  80 +path.speech.line = /data/control/speech/%s/
78 81 \ No newline at end of file
... ...
src/main/resources/application-dev.properties
... ... @@ -71,4 +71,7 @@ sso.enabled= false
71 71 sso.systemcode = SYS0019
72 72 sso.http.url.login= http://180.169.154.251:28090/portal/index.html#/login
73 73 sso.http.url.logout= http://180.169.154.251:18080/information/api/v1/logout
74   -sso.http.url.auth= http://180.169.154.251:18080/information/authenticate/authorityAuthentication
75 74 \ No newline at end of file
  75 +sso.http.url.auth= http://180.169.154.251:18080/information/authenticate/authorityAuthentication
  76 +
  77 +path.speech.common = D:/speech/common/
  78 +path.speech.line = D:/speech/%s/
76 79 \ No newline at end of file
... ...
src/main/resources/application-test.properties
... ... @@ -71,4 +71,7 @@ sso.enabled= false
71 71 sso.systemcode = SYS0023
72 72 sso.http.url.login= https://112.64.45.51/portal/index.html#/login
73 73 sso.http.url.logout= https://112.64.45.51/information/api/v1/logout
74   -sso.http.url.auth= https://112.64.45.51/information/authenticate/authorityAuthentication
75 74 \ No newline at end of file
  75 +sso.http.url.auth= https://112.64.45.51/information/authenticate/authorityAuthentication
  76 +
  77 +path.speech.common = /data/control/speech/common/
  78 +path.speech.line = /data/control/speech/%s/
76 79 \ No newline at end of file
... ...
src/main/resources/static/pages/base/station/js/station-list-table.js
... ... @@ -13,27 +13,40 @@
13 13 */
14 14  
15 15 (function(){
  16 + var code2company = {}, cgsbm = [];
16 17 function getComp(cb) {
17 18 $.get('/user/companyData',null,function(rs) {
18 19 return cb && cb(rs);
19 20 });
20 21 }
21   - function getCompInfo(cb) {
22   - // get请求获取公司
23   - $get('/business/all', {upCode_eq: '88'}, function(gs_d){
24   - return cb && cb(gs_d);
25   - });
26   - }
27   - function gsdmTogsName(gsD,code) {
28   - var rsStr = '';
29   - for(var s = 0 ; s < gsD.length; s++) {
30   - if(gsD[s].businessCode == code) {
31   - rsStr = rsStr + '(' + gsD[s].businessName.replace('公司','') + ')';
32   - break;
  22 + $.ajaxSettings.async = false;
  23 + getComp(function(rs) {
  24 + var html = new Array('<option value="">请选择</option>');
  25 + for (var i = 0;i < rs.length;i++) {
  26 + var item = rs[i], children = item.children;
  27 + var company = {};
  28 + company.name = item.companyName;
  29 + company.children = children;
  30 + for (var j = 0;j < children.length;j++) {
  31 + cgsbm.push(item.companyCode + '_' + children[j].code);
33 32 }
  33 + code2company[item.companyCode] = company;
  34 + html.push('<option value="', item.companyCode, '">', item.companyName, '</option>');
34 35 }
35   - return rsStr;
36   - }
  36 +
  37 + $('#companySelect').html(html.join(''));
  38 + $('#companySelect').on('change', function() {
  39 + var companyCode = $(this).val(), html = ['<option value="">请选择</option>'];
  40 + if (companyCode) {
  41 + for (var i = 0;i < code2company[companyCode].children.length;i++) {
  42 + var item = code2company[companyCode].children[i];
  43 + html.push('<option value="', item.code, '">', item.name, '</option>');
  44 + }
  45 + }
  46 + $('#brancheCompanySelect').html(html.join(''));
  47 + }).trigger('change');
  48 + })
  49 + $.ajaxSettings.async = true;
37 50 function splitxlName(str) {
38 51 var rsStr = '';
39 52 if(str) {
... ... @@ -46,9 +59,9 @@
46 59 if (!$('body').hasClass('page-sidebar-closed')) {$('.menu-toggler.sidebar-toggler').click();}
47 60 /** page : 当前页 initPag : */
48 61 var page = 0,initPag;
49   -
  62 +
50 63 /** 表格数据分页加载 */
51   - loadTableDate(null,true);
  64 + loadTableDate(null, true);
52 65  
53 66 /** 重置按钮事件 */
54 67 $('tr.filter .filter-cancel').on('click',function(){
... ... @@ -57,7 +70,7 @@
57 70 $('.tipso-animation').tipso('hide');
58 71 storage.setItem('xlName_AgursData','');
59 72 // 重新加载表格数据
60   - loadTableDate(null,true);
  73 + loadTableDate(null, true);
61 74 });
62 75  
63 76 /** 搜索按钮事件 */
... ... @@ -109,6 +122,7 @@
109 122 }
110 123 }
111 124 });
  125 +
112 126 return params;
113 127 }
114 128  
... ... @@ -132,10 +146,12 @@
132 146 params['direction'] = 'ASC';
133 147 // 记录当前页数
134 148 params['page'] = page;
  149 + params['cgsbm_in'] = cgsbm.join();
135 150 // 弹出正在加载层
136 151 var i = layer.load(2);
137 152 // 异步请求获取表格数据
138 153 $.get('/station',params,function(result){
  154 + debugger
139 155 var data = {page: page, list: result.content};
140 156 // 把数据填充到模版中
141 157 var tbodyHtml = template('station_datatable_template', data);
... ...
src/main/resources/static/pages/base/station/list.html
... ... @@ -35,12 +35,14 @@
35 35 <th width="6%">序号</th>
36 36 <th width="12%">站点名称</th>
37 37 <th width="12%">站点编码</th>
  38 + <th width="8%">所属公司</th>
  39 + <th width="9%">所属分公司</th>
38 40 <th width="12%">途经线路</th>
39 41 <th width="12%">行业编码</th>
40 42 <th width="12%">东西向</th>
41 43 <th width="12%">南北向</th>
42   - <th width="12%">道路编码</th>
43   - <th width="12%">地址</th>
  44 + <!--<th width="12%">道路编码</th>
  45 + <th width="12%">地址</th>-->
44 46 <th width="10%">操作</th>
45 47 </tr>
46 48 <tr role="row" class="filter">
... ... @@ -52,6 +54,12 @@
52 54 <input type="text" class="form-control form-filter input-sm" id="stationCode" name="stationCode_like">
53 55 </td>
54 56 <td>
  57 + <select name="company_eq" class="form-control" id="companySelect"></select>
  58 + </td>
  59 + <td>
  60 + <select name="brancheCompany_eq" class="form-control" id="brancheCompanySelect"></select>
  61 + </td>
  62 + <td>
55 63 <input type="text" class="form-control form-filter input-sm" id="passLines" name="passLines_like">
56 64 </td>
57 65 <td>
... ... @@ -71,12 +79,12 @@
71 79 <option value="1">北->南</option>
72 80 </select>
73 81 </td>
74   - <td>
  82 + <!--<td>
75 83 <input type="text" class="form-control form-filter input-sm" id="roadCoding" name="roadCoding_eq">
76 84 </td>
77 85 <td>
78 86 <input type="text" class="form-control form-filter input-sm" id="address" name="address_eq">
79   - </td>
  87 + </td>-->
80 88 <td>
81 89 <button class="btn btn-sm green btn-outline filter-submit margin-bottom" >
82 90 <i class="fa fa-search"></i> 搜索
... ...
src/main/resources/static/real_control_v2/fragments/north/nav/dvr.html
... ... @@ -7,7 +7,7 @@
7 7 <div style="display: flex;justify-content:center;align-items: center;height: 603px;">
8 8 <video id="dvr" style="width: 100%;height: 100%"/>
9 9 </div>
10   - <div class="uk-grid" style="margin-left: 0px; margin-top: 20px;">
  10 + <div class="uk-grid" style="margin-left: 0px; margin-top: 20px;" id="ruiming">
11 11 <div class="uk-width uk-width-dvr">
12 12 <div class="uk-panel uk-panel-box uk-panel-box-dvr uk-width-dvr-checked">
13 13 <span data-channel="1">ADAS</span>
... ... @@ -54,12 +54,59 @@
54 54 </div>
55 55 </div>
56 56 </div>
  57 + <div class="uk-grid" style="margin-left: 0px; margin-top: 20px; display: none;" id="tuohua">
  58 + <div class="uk-width uk-width-dvr">
  59 + <div class="uk-panel uk-panel-box uk-panel-box-dvr uk-width-dvr-checked">
  60 + <span data-channel="2-1">ADAS</span>
  61 + </div>
  62 + </div>
  63 + <div class="uk-width uk-width-dvr">
  64 + <div class="uk-panel uk-panel-box uk-panel-box-dvr">
  65 + <span data-channel="2-2">DSM</span>
  66 + </div>
  67 + </div>
  68 + <div class="uk-width uk-width-dvr">
  69 + <div class="uk-panel uk-panel-box uk-panel-box-dvr">
  70 + <span data-channel="1-1">中门</span>
  71 + </div>
  72 + </div>
  73 + <div class="uk-width uk-width-dvr">
  74 + <div class="uk-panel uk-panel-box uk-panel-box-dvr">
  75 + <span data-channel="1-3">车前</span>
  76 + </div>
  77 + </div>
  78 + <div class="uk-width uk-width-dvr">
  79 + <div class="uk-panel uk-panel-box uk-panel-box-dvr">
  80 + <span data-channel="1-4">司机</span>
  81 + </div>
  82 + </div>
  83 + <div class="uk-width uk-width-dvr">
  84 + <div class="uk-panel uk-panel-box uk-panel-box-dvr">
  85 + <span data-channel="1-5">前门</span>
  86 + </div>
  87 + </div>
  88 + <div class="uk-width uk-width-dvr">
  89 + <div class="uk-panel uk-panel-box uk-panel-box-dvr">
  90 + <span data-channel="1-6">前车厢</span>
  91 + </div>
  92 + </div>
  93 + <div class="uk-width uk-width-dvr">
  94 + <div class="uk-panel uk-panel-box uk-panel-box-dvr">
  95 + <span data-channel="1-7">后车厢</span>
  96 + </div>
  97 + </div>
  98 + <div class="uk-width uk-width-dvr">
  99 + <div class="uk-panel uk-panel-box uk-panel-box-dvr">
  100 + <span data-channel="1-8">360</span>
  101 + </div>
  102 + </div>
  103 + </div>
57 104 </div>
58 105 <script>
59 106 (function() {
60 107 var player, requesting = false, info;
61 108 $('.uk-panel-box-dvr span').on('click', function() {
62   - var channel = $(this).data('channel');
  109 + var channel = $(this).data('channel') + '', param = {sim: info.sim, channel: channel};
63 110 if (requesting) {
64 111 layer.msg('正在请求播放地址,请等待')
65 112 return;
... ... @@ -67,7 +114,12 @@
67 114 requesting = true;
68 115 $('.uk-width-dvr-checked').removeClass('uk-width-dvr-checked');
69 116 $(this).parent().addClass('uk-width-dvr-checked');
70   - $.post('/dvr/jt1078', {sim: info.sim, channel: channel}, function(res) {
  117 + if (channel.indexOf('-') > -1) {
  118 + var no = channel.split('-')[0], channelNum = channel.split('-')[1];
  119 + param.sim = no === '1' ? info.sim : info.sim2;
  120 + param.channel = channelNum;
  121 + }
  122 + $.post('/dvr/jt1078', param, function(res) {
71 123 requesting = false;
72 124 if (res.status == 'SUCCESS') {
73 125 if (player) {
... ... @@ -90,7 +142,11 @@
90 142 $('#dvr-modal').on('init', function(e, data) {
91 143 info = data;
92 144 requesting = true;
93   - $.post('/dvr/jt1078', {sim: info.sim, channel: 1}, function(res) {
  145 + if (info.sim2) {
  146 + $('#ruiming').css('display', 'none');
  147 + $('#tuohua').css('display', 'block');
  148 + }
  149 + $.post('/dvr/jt1078', {sim: info.sim2 ? info.sim2 : info.sim, channel: 1}, function(res) {
94 150 requesting = false;
95 151 if (res.status == 'SUCCESS') {
96 152 player = videojs('dvr', {sources: [{src: res.data['hls']}], autoplay: true});
... ...
src/main/resources/static/real_control_v2/mapmonitor/fragments/map_infowindow.html
... ... @@ -70,7 +70,7 @@
70 70 {{if expectStopTime!=null}}
71 71 <a href="javascript:;" style="color: #07D;margin-right: 7px;">预计 {{expectStopTime}} 分钟到达终点</a>
72 72 {{/if}}
73   - <a href="javascript:;" style="float: left;" onclick="javascript:gb_map_dvr.openDvr({sim: '{{sim}}'})">DVR</a>
  73 + <a href="javascript:;" style="float: left;" onclick="javascript:gb_map_dvr.openDvr({nbbm: '{{nbbm}}', sim: '{{sim}}', sim2: '{{sim2}}'})">DVR</a>
74 74 {{if dvrcode != null}}<a href="javascript:void(0)" style="margin-left: 50px;" >拨打电话</a>{{/if}}
75 75 <a href="javascript:;" style="float: right;" onclick="javascript:gb_map_play_back.initParams({deviceId: '{{deviceId}}', nbbm: '{{nbbm}}'});">轨迹回放</a>
76 76 </div>
... ...