全部产品

OPUS格式语音编解码

更新时间:2017-06-07 13:26:11   分享:   

OPUS 编码使用说明

简介

Opus编码器 是一个有损声音编码的格式,由互联网工程任务组(IETF)进来开发,适用于网络上的实时声音传输,标准格式为RFC 6716。Opus 格式是一个开放格式,使用上没有任何专利或限制。

  • Bitrates from 6 kb/s to 510 kb/s
  • Sampling rates from 8 kHz (narrowband) to 48 kHz (fullband)
  • Frame sizes from 2.5 ms to 60 ms
  • Support for both constant bitrate (CBR) and variable bitrate (VBR)
  • Audio bandwidth from narrowband to fullband
  • Support for speech and music
  • Support for mono and stereo

OPUS 在NLS服务中的使用

目前我们的Android 和 iOS客户端sdk中集成了OPUS编码(encoder)功能。根据我们的参数进行语音编解码,可以做到大概9:1的语音压缩比,能够有效的节省传输带宽和响应时间。

在使用Java SDK时,SDK本身不支持OPUS的编解码,我们提供了使用JNI方式调用Opus的编解码工具,用户可以通过下面的代码自行编译动态链接库。

官方OPUS下载

opus更详细的说明请参考 http://www.opus-codec.org/

opus版本请使用1.0.3以上版本 http://www.opus-codec.org/downloads/older.shtml.en ,下载libopus Source code。

接口说明: http://www.opus-codec.org/docs/html_api-1.0.3/index.html

调用方式

通过JNI方式调用官方opus( http://www.opus-codec.org ) 编译出的.so(动态链接库)实现。

编译nls opus so(linux环境)

  • 下载官方opus(如1.1.3版本)Source code并解压。
  • 在解压目录*/opus 编译opus: make -f Makefile -j8
  • 拷贝NLS调用文件OpuCodec.c 至*/opus/.libs/ 下。
  • 使用gcc 编译OpusCodec并链接libopus。
    1. -- linux : g++ OpuCodec.c -I ../include/ -I /\*/jdk/include/ -I /\*/jdk/include/linux/ -L. -lopus -shared -fPIC -o libopucodec.so

调用链接库(linux环境)

在*/opus/.libs/下会有两个so,libopucodec.so以及libopus.so.0。

在项目导入上述两个so,或者将libopucodec.so以及libopus.so.0拷贝到/usr/lib64/ 目录下。 或者使用指定java运行时lib目录:-Djava.library.path=./libs。如果提示确实libopus的问题,ldd 查看libopucodec.so是否链接上libopus.so.0.

调用实现:

NLS OPUS 的实现通过调用官方OPUS库实现,调用方式如下:

OpuCodec.c:

  1. #include <jni.h>
  2. #include <opus.h>
  3. #include <opus_defines.h>
  4. /* Header for class com_aliyun_nls_transcription_opu_OpuCodec */
  5. const int FRAME_SAMPLES = 320;
  6. #ifndef _Included_com_aliyun_nls_transcription_opu_OpuCodec
  7. #define _Included_com_aliyun_nls_transcription_opu_OpuCodec
  8. #ifdef __cplusplus
  9. extern "C" {
  10. #endif
  11. /*
  12. * Class: com_aliyun_nls_transcription_opu_OpuCodec
  13. * Method: createEncoder
  14. * Signature: ()J
  15. */
  16. JNIEXPORT jlong JNICALL Java_com_aliyun_nls_transcription_opu_OpuCodec_createEncoder
  17. (JNIEnv *, jobject);
  18. /*
  19. * Class: com_aliyun_nls_transcription_opu_OpuCodec
  20. * Method: createDecoder
  21. * Signature: ()J
  22. */
  23. JNIEXPORT jlong JNICALL Java_com_aliyun_nls_transcription_opu_OpuCodec_createDecoder
  24. (JNIEnv *, jobject);
  25. /*
  26. * Class: com_aliyun_nls_transcription_opu_OpuCodec
  27. * Method: encode
  28. * Signature: (J[SI[B)I
  29. */
  30. JNIEXPORT jint JNICALL Java_com_aliyun_nls_transcription_opu_OpuCodec_encode
  31. (JNIEnv *, jobject, jlong, jshortArray, jint, jbyteArray);
  32. /*
  33. * Class: com_aliyun_nls_transcription_opu_OpuCodec
  34. * Method: decode
  35. * Signature: (J[BI[S)I
  36. */
  37. JNIEXPORT jint JNICALL Java_com_aliyun_nls_transcription_opu_OpuCodec_decode
  38. (JNIEnv *, jobject, jlong, jbyteArray, jint, jshortArray);
  39. /*
  40. * Class: com_aliyun_nls_transcription_opu_OpuCodec
  41. * Method: destroyEncoder
  42. * Signature: (J)V
  43. */
  44. JNIEXPORT void JNICALL Java_com_aliyun_nls_transcription_opu_OpuCodec_destroyEncoder
  45. (JNIEnv *, jobject, jlong);
  46. /*
  47. * Class: com_aliyun_nls_transcription_opu_OpuCodec
  48. * Method: destroyDecoder
  49. * Signature: (J)V
  50. */
  51. JNIEXPORT void JNICALL Java_com_aliyun_nls_transcription_opu_OpuCodec_destroyDecoder
  52. (JNIEnv *, jobject, jlong);
  53. /*
  54. * Class: com_aliyun_nls_transcription_opu_OpuCodec
  55. * Method: createEncoder
  56. * Signature: ()J
  57. */
  58. JNIEXPORT jlong JNICALL Java_com_aliyun_nls_transcription_opu_OpuCodec_createEncoder
  59. (JNIEnv* env, jobject thiz){
  60. int error;
  61. OpusEncoder *pOpusEnc = opus_encoder_create(16000, 1, OPUS_APPLICATION_VOIP,
  62. &error);
  63. if (pOpusEnc) {
  64. opus_encoder_ctl(pOpusEnc, OPUS_SET_VBR(1));
  65. opus_encoder_ctl(pOpusEnc, OPUS_SET_BITRATE(27800));
  66. opus_encoder_ctl(pOpusEnc, OPUS_SET_COMPLEXITY(8));
  67. opus_encoder_ctl(pOpusEnc, OPUS_SET_SIGNAL(OPUS_SIGNAL_VOICE));
  68. }
  69. return (jlong) pOpusEnc;
  70. }
  71. JNIEXPORT jlong JNICALL Java_com_aliyun_nls_transcription_opu_OpuCodec_createDecoder
  72. (JNIEnv* env, jobject thiz){
  73. int error;
  74. OpusDecoder *pOpusDec = opus_decoder_create(16000, 1, &error);
  75. return (jlong) pOpusDec;
  76. }
  77. //encode
  78. //(JNIEnv *, jobject, jlong, jshortArray, jint, jbyteArray);
  79. JNIEXPORT jint JNICALL Java_com_aliyun_nls_transcription_opu_OpuCodec_encode
  80. (JNIEnv* env,jobject thiz, jlong pOpusEnc, jshortArray samples, jint offset,
  81. jbyteArray bytes){
  82. OpusEncoder *pEnc = (OpusEncoder*) pOpusEnc;
  83. if (!pEnc || !samples || !bytes)
  84. return 0;
  85. jshort *pSamples = env->GetShortArrayElements(samples, 0);
  86. jsize nSampleSize = env->GetArrayLength(samples);
  87. jbyte *pBytes = env->GetByteArrayElements(bytes, 0);
  88. jsize nByteSize = env->GetArrayLength(bytes);
  89. if (nSampleSize-offset < FRAME_SAMPLES || nByteSize <= 0)
  90. return 0;
  91. int nRet = opus_encode(pEnc, pSamples+offset, FRAME_SAMPLES, (unsigned char*)pBytes, nByteSize);
  92. env->ReleaseShortArrayElements(samples, pSamples, 0);
  93. env->ReleaseByteArrayElements(bytes, pBytes, 0);
  94. return nRet;
  95. }
  96. JNIEXPORT jint JNICALL Java_com_aliyun_nls_transcription_opu_OpuCodec_decode
  97. (JNIEnv* env, jobject thiz, jlong pOpusDec, jbyteArray bytes, jint bytelength, jshortArray samples){
  98. OpusDecoder *pDec = (OpusDecoder*) pOpusDec;
  99. if (!pDec || !samples || !bytes)
  100. return 0;
  101. jshort *pSamples = env->GetShortArrayElements(samples, 0);
  102. jbyte *pBytes = env->GetByteArrayElements(bytes, 0);
  103. jsize nByteSize = env->GetArrayLength(bytes);
  104. // jint nbyte = bytes[0];
  105. if (bytelength<=0)
  106. {
  107. return -1;
  108. }
  109. int nRet = opus_decode(pDec, (unsigned char*)pBytes, bytelength, pSamples, FRAME_SAMPLES, 0);
  110. env->ReleaseShortArrayElements(samples, pSamples, 0);
  111. env->ReleaseByteArrayElements(bytes, pBytes, 0);
  112. return nRet;
  113. }
  114. JNIEXPORT void JNICALL Java_com_aliyun_nls_transcription_opu_OpuCodec_destroyEncoder
  115. (JNIEnv* env, jobject thiz, jlong pOpusEnc){
  116. OpusEncoder *pEnc = (OpusEncoder*) pOpusEnc;
  117. if (!pEnc)
  118. return;
  119. opus_encoder_destroy(pEnc);
  120. }
  121. JNIEXPORT void JNICALL Java_com_aliyun_nls_transcription_opu_OpuCodec_destroyDecoder
  122. (JNIEnv* env, jobject thiz, jlong pOpusDec){
  123. OpusDecoder *pDec = (OpusDecoder*) pOpusDec;
  124. if (!pDec)
  125. return;
  126. opus_decoder_destroy(pDec);
  127. }
  128. #ifdef __cplusplus
  129. }
  130. #endif
  131. #endif

上述OpuCodec.c可以编译成.so 动态链接库提供给Java程序调用。通过JNI方式调用NLS OPUS 动态链接库的代码为:

src/main/java/com/aliyun/nls/transcription/opu/OpuCodec.java

  1. package com.aliyun.nls.transcription.opu;
  2. public class OpuCodec {
  3. static {
  4. System.loadLibrary("opucodec");
  5. }
  6. public native long createEncoder();
  7. public native long createDecoder();
  8. public native int encode(long handle, short[] lin, int offset, byte[] encoded);
  9. public native int decode(long handle, byte[] encoded, int byteNum, short[] lin);
  10. public native void destroyEncoder(long handle);
  11. public native void destroyDecoder(long handle);
本文导读目录
本文导读目录
以上内容是否对您有帮助?