语音聊天室

聊天设备

1 双方之间的网络连接 要进行频数据的传输,首先就是要建立数据连结。常用的通讯协议中,TCP较可靠,所以用在不允许数据丢失的应用上。而UDP则较多应用于处理速度要求较快、数据传输可靠性要求不是很高的应用上,如数据广播。通信协议的选择取决于我们所要做的应用的类型。怎样建立网络连接,稳定的接收和发送音频信号的数据流是关键。

基本介绍
在网络上传输音频的方面存在的问题主要可以归纳为以下几点:
信号采集回放
在进行音频信号的采集中我们必须考虑到采样率的问题,声音信号的采样率有8Khz、16Khz、32Khz、44Khz等,每种数据采样虑产生的数据量都不一样,越高的采样率产生的数据量越大,所以我们要选择合适的采样率以适应网络的带宽。
信号编码解码
如果把直接采集到的音频信号数据流在网络上进行传输,它所占有的带宽也是十分大的,以8Khz的采样率采集14位的音频数据那么就有以下这样的一个式子:
从中我们可以看出以这样的方式传输音频数据,每秒需要向网络中发送112kb的数据。所以。从节省带宽的角度考虑,我们很有必要对这样的数据进行压缩。对多媒体信号的压缩我们有许多可以选择的格式,如mp2、mp3、GSM等等,现在用的最多的是MP3格式。同样,我们这里也存在一个对压缩格式进行选择的问题,考虑到音频数据传输的及时性,对传输的音频数据质量的要求,以及各种压缩格式的压缩比率以及进行压缩和解压缩所要耗费的系统资源等方面问题,选择合适的压缩格式就显得尤为重要。
解决方法
下面就针对前面提出的问题讨论一下解决的办法
双方之间的网络连接
在这方面有其独特的优势,Java提供了丰富的网络类库的支持,可以轻松编写多种类型的网络通信程序。在我下面的例子中我就使用了TCP/IP协议,通过Java的Socket类进行编程2 音频信号的采集和回放以及音频数字信号的编码与解码 在解决这两个问题的时候,在网上很幸运地通过一些文章的介绍,找到了Answer Machine 演示程序的源代码(由of j的Florian Bomers 和Matthias Pfisterer编写,网址在这个程序代码中,有几个解决我们问题所需要的类,而且作者将这些类封装的很好,我们基本不需要做什么改动,只需要屏蔽其中的调试信息的输出就行了,更可贵的是它还封装了几种常见的音频格式。其中的GSM格式(Global System for Mobile Telecommunications)就是我们下面例子中采用的压缩格式,GSM格式可以将128kbps 的音频数据流 (16bit通过8k Hz的音频采样) 压缩为13kbps 的音频数据流,非常适合语音信号的传送,所以可谓是一石二鸟。
介绍
“考米网”是深圳市盈华讯方通信技术有限公司领先推出的能够电话聊天交友的网站,在网络交友的基础上增添电话聊天,提供一对一通话、多人通话、二人电话约会、自建会议聊天室、电话中发送的语音短讯,设置个性化个人资料等十几种功能。在不方便使用电脑的时候,也能通过手机、电话拨打400热线,随时和网上的好友保持联系。
2、YY聊天
是一种YY团队语音工具,是多玩游戏网针对中文用户设计的多人语音群聊工具。 它是一款免费语音软件,稳定清晰的语音工具,用于游戏玩家交流等。即时通话,是一款不错的通讯软件。
3、ISpeak
ISpeak娱乐互动平台(简称IS),是国内专业游戏语音服务商,拥有上千万注册用户,每天活跃用户上百万,公会频道近10万个的规模,已经成为国内一流的语音互动平台。
IS以网络游戏用户为基础,提供专业的语音、聊天、社区论坛等。为用户提供免费的语音频道和无偿服务;为公会提供一个更好的实现自我平台,促进和扶持公会的成长;为厂商提供一个游戏推广,服务玩家的超大型互动娱乐社区。
4、QQ语音
腾讯公司一直为使用QQ的用户提供语音聊天服务。其语音聊天的缺点是通话质量差,只能电脑对电脑传播,所以一直没有大范围传播开。
源代码分析
我分析过这几个类的源代码,不得不佩服它的作者,每个类的源代码都很精炼,大家可以自己分析一下。好了下面就给大家讲讲这几个类,并且将它们用到的Java Sound API中的类和函数等一并做个简单介绍,让大家对Java Sound API中常用的类也有个大致的了解。由于Java Sound API中的类比较多。限于篇幅无法对所有用到的类做详尽的解释,以下内容只是简单提及了各个类的用途和使用规范,有关Java Sound API中类的具体介绍请大家访问这里[url=http://java./j2se/1.4.2/docs/api/]查找javax.sound.sampled的相关内容。
以下的提到几个文件是从Answer Machine 演示程序的源代码中提取出来的,由于是开放源代码的程序,大家在使用的时候请注意相关的
公共协议
AMAudioFormat类(封装在AMAudioFormat.java文件中)
AMAudioFormat类封装了CD、FM、TELEPHONE、GSM这四种质量的音频格式的参数,使用起来也非常简单,这样我们在使用Java Sound API时就不用自己去写那些复杂的代码了,但为了明白Java Sound API的原理,我们需要对它的代码做一下分析。它使用了Java Sound API中的AudioFormat这个类,这个类非常重要,在Java中对任何音频数据的使用都要实现通过它指定所需要使用的音频格式,AudioFormat类有一个嵌套的类AudioFormat.Encoding,实际上大部分对AudioFormat类的使用都是使用的这个嵌套的类。
AMAudioFormat类的重要方法:
名称:getLineAudioFormat
调用格式:getLineAudioFormat(整型音频格式代号)
返回值: 根据传递音频格式代号生成的AudioFormat对象。
说道这里大家可能要问了,那么通过Java Sound API可以直接使用GSM格式吗?答案是比较复杂,但同样有解决的办法,作者在这里使用了另外的开源程序的类库-tritonus的GSM编码解码库。大家需要在这里下载tritonous_share.jar和tritonus_gsm.jar两个文件,并在AMAudioFormat类中引用,这样就完成了GSM格式的设置。需要告诉大家的是在对AMAudioFormat.java这个类进行编译后,我们的程序运行的时候就可以不需要tritonous_share.jar和tritonus_gsm.jar这两个文件的支持了。
(封装在AudioCapture.java文件中)2
AudioCapture类封装了从音频硬件捕获音频数据并自动编码为GSM音频压缩数据的过程,并且通过它的getAudioInputStream()方法提供给我们一个音频数据输入流,我们就可以直接将这个流发送到网络中。
AudioCapture 类的重要方法:
名称:getAudioInputStream
调用格式:getAudioInputStream()
返回值:AudioInputStream对象
AudioCapture 类使用了Java Sound API中的AudioInputStream、AudioFormat、AudioSystem这几个类和TargetDataLine、LineListener接口。除了AudioFormat类我再简单介绍一下其他的类:
AudioInputStream 类是带有特殊音频格式和长度的InputStream类,它有两个构造方法,分别是AudioInputStream(InputStream stream, AudioFormat format,long length)和AudioInputStream(TargetData -Line line)。
TargetDataLine 接口是DataLine接口的一种,通过它就可以直接从音频硬件获取数据了,它有几个常用的方法,分别是:open(AudioFormat format)、void open(AudioFormat format, int bufferSize)、int read(byte[] b, int off, int len)。
AudioSystem 类是Java标准音频系统的入口点,在AudioSystem 类中使用他的getLine() 方法创建TargetDataLine对象。
LineListener接口用来对线路状态改变的时间进行监听,他的重要的方法是update(LineEvent event)方法。
(封装在AudioPlayStream.java文件中)
AudioPlayStream类与AudioCapture类刚好相反,它封装了GSM压缩音频数据的解码和音频信号的回放过程,提供给我们一个音频信号输出流。AudioCapture类用到的Java Sound API中的类它也基本都用到了,只是它使用了SourceDataLine接口而不是TargetDataLine接口
(封装在Debug.java文件中)
Debug类主要用来在调试时输出讯息,代码很少,后来我把其中输出信息的语句都屏蔽了,对程序运行没有影响。
为了方便使用以上的几个类,我们需要对它们进行编译和打包,编译时需要设置相关的编译环境,以下是我们需要用到的命令行
说明一下,我将以上提到的Java源码文件放在了am目录下,编译之后可以得到一个8k的am.jar文件,我们下一步所需要做的就是在我们的程序中引用这个包。
实例介绍
有了以上的基本的介绍,我就可以通过对我写的一个极为简单的语音对讲软件代码的解释让大家更清楚地了解一下这几个模块的具体使用方法,大家可以从中获得开发具有诸如网络电话、自动应答等功能的软件的类似方法,用于语音数据的传输。
程序的结构
整个程序分三层,作用分别如下:
. 顶层: 用户界面
. 中间层: 控制层
. 底层: 传输层
程序有两个主要的类: (表)
类名描述
CallLink 网络传输层,用于接收或发送音频数据。
VoiceSender 作为第二个启动的线程提供从音频硬件捕获并编码好的数据给网络传输层。
程序的主类jphone使用了Runnable和ActionListener接口,主类除了基本的几个方法之外,还具有方法initAudioHardware()、ShowMSG、startPhone分别用于初始化AudioCapture类与AudioPlayStream类、显示程序状态和开始程序。主类jphone具有两个子类VoiceSender和CallLink。
子类VoiceSender同样使用了Runnable接口,它在程序中作为第二个启动的线程负责发送捕获到的音频数据。CallLink子类就是负责建立scoket连接,并且负责接收或发送网络数据、监听网络连接等功能的实现。它具有主要的方法是getInputStream()、getOutputStream()、listen()、open()、close()等。
为了让大家更清楚的了解程序的结构请大家看下面的类图。
程序工作流程
当程序启动时首先执行建立当前主类的实例,当按下呼叫按钮的时候执行startPhone()方法,startPhone()方法通过调用initAudioHardware()方法建立AudioCapture对象和AudioPlayStream对象的实例PhoneMIC和PhoneSPK, 紧接着在建立CallLink子类的实例curCallLink来与具有目标IP地址的计算机进行scoket连接后,startPhone()方法又将子类VoiceSender作为secondThread线程启动,然后又调用run()方法。 run()方法通过已经建立的CallLink子类的实例curCallLink监听网络上的数据(也就是等待别人的呼叫),一旦有音频数据到来curCallLink 实例就为AudioPlayStream 对象PhoneSPK 提供网络传来的音频数据,而PhoneSPK在一个循环中不断的将音频数据转换为音频信号,完成类似电话听筒的功能。
子类VoiceSender 就作为第二线程启动的时候,startPhone() 方法传递给它的参数是实例化的CallLink 子类curCallLink , 子类VoiceSender 通过实例化的AudioCapture 对象PhoneMIC 将音频信号压缩成GSM数据,并通过curCallLink 将音频数据发送到具有目标IP 地址的计算机上,完成类似电话受话器的功能。
在这里实例化的CallLink 子类curCallLink 就相当于两个电话之间的电话线,这样通过我以上的解释大家对程序的原理就有一个大概的了解了吧。
其中的音频数据发送线程和音频数据接收线程是同步的,不过考虑到网络的因素,可能在声音的传输上有一些延迟,不过由于延迟比较小对及时听到对方的话语影响不大。
编写代码摘要
在使用AudioCapture 类和AudioPlayStream 类的方法之前需要知道怎样初始化这两个类。在声明AudioCapture 对象的时候需要传递给它一个静态的整型值用于表达将音频信号压缩的方式,这个静态的整型常量可以是AMAudioFormat 类的以下四个值之一: FORMAT_CODE_CD 、FORMAT_CODE_FM 、FORMAT
所以声明AudioCapture 对象就要用一下的形式:
private AudioCapture PhoneMIC null;
PhoneMIC new AudioCapture
FORMAT_CODE_GSM);
而声明AudioPlayStream 对象则不同,我们在初始化它的时候需要传递给它一个AudioFormat 对象,用于通知它我们所要播放音频的格式,这个AudioFormat 对象可以通过AMAudioFormat 类的getLineAudioFormat(格式参数值)方法获得,其中格式参数的取值和上面提到过的AMAudioFormat 的四个值相同,所以声明AudioPlayStream 对象就要用以下的形式:
private AudioPlayStream PhoneSPK null;
在这之后就可以使用AudioCapture 和AudioPlayStream 对象的open() 方法打开音频捕获和音频回放通道完成它们的初始化了。如以下的形式:
PhoneMIC.open();
PhoneSPK.open();
初始化完成之后要使AudioPlayStream 对象播放声音还需要以下过程,首先建立一个缓冲区(字节数组)用于存放从网络传来的音频数据流,然后执行AudioPlayStream 对象的start() 方法使AudioPlayStream
对象开始声音的回放,这时执行一个while 循环,在循环中将音频流数据写入缓冲区,再使用AudioPlayStream对象的write()方法将缓冲区的数据还原成语音信号然后播放出来。如下面的例子:
其中complete 的值用于标志终止声音播放的异常原因。
类似的,初始化完成之后要使AudioCapture 对象捕获和压缩声音数据还需要其他的操作,首先声明一个InputStream 对象,赋其值为AudioCapture 对象的getAudioInputStream() 方法的返回值,执行
对象的start() 方法,然后在建立一个循环,将通过InputStream 的read() 方法得到的数据发送到网络上。例如以下代码:
sendStream.write(compressedVoice,0,b);
......
通过使用CallLink 的几个方法,我们可以方便的传输和接收音频数据流。以下是它的代码:
//使用套接字进行连接
void open() throws IOException, UnknownHostException
//打开网路连接
// 监听,等候呼叫
inServSock new ServerSocket(TALK_PORT);
inSock inServSock.accept();
public InputStream getInputStream()throws IOException
//返回音频数据输入流
H if (inSock != null)
return inSock.getInputStream();
else
return null;
publicOutputStreamgetOutputStream()throwsIOException
//返回音频数据输出流
if (outSock != null)
return outSock.getOutputStream();
else
return null;
void close() throws IOException
//关闭网络连接 ;
inSock.close();
outSock.close();
程序的代码总体有366 行,限于篇幅,这里就不一一列举了。
编译以及程序的使用方法:
运行和编译本程序需要加上额外的环境参数,为了方便使用可以建立以下内容的批处理文件:(假设程序所需要的包均在程序所在目录下的lib 文件夹中)
用于编译的批处理程序c.bat 的内容
用于运行的批处理程序r.bat 的内容
启动时在A 计算机的IP 地址框内输入要进行连接的计算机B 的IP 地址,在计算机B 的IP 地址框内输入要进行连接的计算机A 的IP 地址,让后分别点击“拨出电话”按钮就可以进行连接了。当然别忘了接上麦克风和打开音箱电源,呵呵。
提醒大家,这里的IP 地址栏里预先存在的地址是127.0.0.1,也就是说,程序也可以和自己进行连接,点击“拨出电话”按钮,等8 秒左右敲敲你的麦克风,听到没有,是不是也有“嘣、嘣、嘣”的声音??
全国各地天气预报查询

上海市

  • 市辖区
  • 云南省

  • 临沧市
  • 云南省

  • 丽江市
  • 云南省

  • 保山市
  • 云南省

  • 大理白族自治州
  • 云南省

  • 德宏傣族景颇族自治州
  • 云南省

  • 怒江傈僳族自治州
  • 云南省

  • 文山壮族苗族自治州
  • 云南省

  • 昆明市
  • 云南省

  • 昭通市
  • 云南省

  • 普洱市
  • 云南省

  • 曲靖市
  • 云南省

  • 楚雄彝族自治州
  • 云南省

  • 玉溪市
  • 云南省

  • 红河哈尼族彝族自治州
  • 云南省

  • 西双版纳傣族自治州
  • 云南省

  • 迪庆藏族自治州
  • 内蒙古自治区

  • 乌兰察布市
  • 内蒙古自治区

  • 乌海市
  • 内蒙古自治区

  • 兴安盟
  • 内蒙古自治区

  • 包头市
  • 内蒙古自治区

  • 呼伦贝尔市
  • 内蒙古自治区

  • 呼和浩特市
  • 内蒙古自治区

  • 巴彦淖尔市
  • 内蒙古自治区

  • 赤峰市
  • 内蒙古自治区

  • 通辽市
  • 内蒙古自治区

  • 鄂尔多斯市
  • 内蒙古自治区

  • 锡林郭勒盟
  • 内蒙古自治区

  • 阿拉善盟
  • 北京市

  • 市辖区
  • 吉林省

  • 吉林市
  • 吉林省

  • 四平市
  • 吉林省

  • 延边朝鲜族自治州
  • 吉林省

  • 松原市
  • 吉林省

  • 白城市
  • 吉林省

  • 白山市
  • 吉林省

  • 辽源市
  • 吉林省

  • 通化市
  • 吉林省

  • 长春市
  • 四川省

  • 乐山市
  • 四川省

  • 内江市
  • 四川省

  • 凉山彝族自治州
  • 四川省

  • 南充市
  • 四川省

  • 宜宾市
  • 四川省

  • 巴中市
  • 四川省

  • 广元市
  • 四川省

  • 广安市
  • 四川省

  • 德阳市
  • 四川省

  • 成都市
  • 四川省

  • 攀枝花市
  • 四川省

  • 泸州市
  • 四川省

  • 甘孜藏族自治州
  • 四川省

  • 眉山市
  • 四川省

  • 绵阳市
  • 四川省

  • 自贡市
  • 四川省

  • 资阳市
  • 四川省

  • 达州市
  • 四川省

  • 遂宁市
  • 四川省

  • 阿坝藏族羌族自治州
  • 四川省

  • 雅安市
  • 天津市

  • 市辖区
  • 宁夏回族自治区

  • 中卫市
  • 宁夏回族自治区

  • 吴忠市
  • 宁夏回族自治区

  • 固原市
  • 宁夏回族自治区

  • 石嘴山市
  • 宁夏回族自治区

  • 银川市
  • 安徽省

  • 亳州市
  • 安徽省

  • 六安市
  • 安徽省

  • 合肥市
  • 安徽省

  • 安庆市
  • 安徽省

  • 宣城市
  • 安徽省

  • 宿州市
  • 安徽省

  • 池州市
  • 安徽省

  • 淮北市
  • 安徽省

  • 淮南市
  • 安徽省

  • 滁州市
  • 安徽省

  • 芜湖市
  • 安徽省

  • 蚌埠市
  • 安徽省

  • 铜陵市
  • 安徽省

  • 阜阳市
  • 安徽省

  • 马鞍山市
  • 安徽省

  • 黄山市
  • 山东省

  • 东营市
  • 山东省

  • 临沂市
  • 山东省

  • 威海市
  • 山东省

  • 德州市
  • 山东省

  • 日照市
  • 山东省

  • 枣庄市
  • 山东省

  • 泰安市
  • 山东省

  • 济南市
  • 山东省

  • 济宁市
  • 山东省

  • 淄博市
  • 山东省

  • 滨州市
  • 山东省

  • 潍坊市
  • 山东省

  • 烟台市
  • 山东省

  • 聊城市
  • 山东省

  • 菏泽市
  • 山东省

  • 青岛市
  • 山西省

  • 临汾市
  • 山西省

  • 吕梁市
  • 山西省

  • 大同市
  • 山西省

  • 太原市
  • 山西省

  • 忻州市
  • 山西省

  • 晋中市
  • 山西省

  • 晋城市
  • 山西省

  • 朔州市
  • 山西省

  • 运城市
  • 山西省

  • 长治市
  • 山西省

  • 阳泉市
  • 广东省

  • 东莞市
  • 广东省

  • 中山市
  • 广东省

  • 云浮市
  • 广东省

  • 佛山市
  • 广东省

  • 广州市
  • 广东省

  • 惠州市
  • 广东省

  • 揭阳市
  • 广东省

  • 梅州市
  • 广东省

  • 汕头市
  • 广东省

  • 汕尾市
  • 广东省

  • 江门市
  • 广东省

  • 河源市
  • 广东省

  • 深圳市
  • 广东省

  • 清远市
  • 广东省

  • 湛江市
  • 广东省

  • 潮州市
  • 广东省

  • 珠海市
  • 广东省

  • 肇庆市
  • 广东省

  • 茂名市
  • 广东省

  • 阳江市
  • 广东省

  • 韶关市
  • 广西壮族自治区

  • 北海市
  • 广西壮族自治区

  • 南宁市
  • 广西壮族自治区

  • 崇左市
  • 广西壮族自治区

  • 来宾市
  • 广西壮族自治区

  • 柳州市
  • 广西壮族自治区

  • 桂林市
  • 广西壮族自治区

  • 梧州市
  • 广西壮族自治区

  • 河池市
  • 广西壮族自治区

  • 玉林市
  • 广西壮族自治区

  • 百色市
  • 广西壮族自治区

  • 贵港市
  • 广西壮族自治区

  • 贺州市
  • 广西壮族自治区

  • 钦州市
  • 广西壮族自治区

  • 防城港市
  • 新疆维吾尔自治区

  • 乌鲁木齐市
  • 新疆维吾尔自治区

  • 伊犁哈萨克自治州
  • 新疆维吾尔自治区

  • 克孜勒苏柯尔克孜自治州
  • 新疆维吾尔自治区

  • 克拉玛依市
  • 新疆维吾尔自治区

  • 博尔塔拉蒙古自治州
  • 新疆维吾尔自治区

  • 吐鲁番市
  • 新疆维吾尔自治区

  • 和田地区
  • 新疆维吾尔自治区

  • 哈密市
  • 新疆维吾尔自治区

  • 喀什地区
  • 新疆维吾尔自治区

  • 塔城地区
  • 新疆维吾尔自治区

  • 巴音郭楞蒙古自治州
  • 新疆维吾尔自治区

  • 昌吉回族自治州
  • 新疆维吾尔自治区

  • 自治区直辖县级行政区划
  • 新疆维吾尔自治区

  • 阿克苏地区
  • 新疆维吾尔自治区

  • 阿勒泰地区
  • 江苏省

  • 南京市
  • 江苏省

  • 南通市
  • 江苏省

  • 宿迁市
  • 江苏省

  • 常州市
  • 江苏省

  • 徐州市
  • 江苏省

  • 扬州市
  • 江苏省

  • 无锡市
  • 江苏省

  • 泰州市
  • 江苏省

  • 淮安市
  • 江苏省

  • 盐城市
  • 江苏省

  • 苏州市
  • 江苏省

  • 连云港市
  • 江苏省

  • 镇江市
  • 江西省

  • 上饶市
  • 江西省

  • 九江市
  • 江西省

  • 南昌市
  • 江西省

  • 吉安市
  • 江西省

  • 宜春市
  • 江西省

  • 抚州市
  • 江西省

  • 新余市
  • 江西省

  • 景德镇市
  • 江西省

  • 萍乡市
  • 江西省

  • 赣州市
  • 江西省

  • 鹰潭市
  • 河北省

  • 保定市
  • 河北省

  • 唐山市
  • 河北省

  • 廊坊市
  • 河北省

  • 张家口市
  • 河北省

  • 承德市
  • 河北省

  • 沧州市
  • 河北省

  • 石家庄市
  • 河北省

  • 秦皇岛市
  • 河北省

  • 衡水市
  • 河北省

  • 邢台市
  • 河北省

  • 邯郸市
  • 河南省

  • 三门峡市
  • 河南省

  • 信阳市
  • 河南省

  • 南阳市
  • 河南省

  • 周口市
  • 河南省

  • 商丘市
  • 河南省

  • 安阳市
  • 河南省

  • 平顶山市
  • 河南省

  • 开封市
  • 河南省

  • 新乡市
  • 河南省

  • 洛阳市
  • 河南省

  • 漯河市
  • 河南省

  • 濮阳市
  • 河南省

  • 焦作市
  • 河南省

  • 省直辖县级行政区划
  • 河南省

  • 许昌市
  • 河南省

  • 郑州市
  • 河南省

  • 驻马店市
  • 河南省

  • 鹤壁市
  • 浙江省

  • 丽水市
  • 浙江省

  • 台州市
  • 浙江省

  • 嘉兴市
  • 浙江省

  • 宁波市
  • 浙江省

  • 杭州市
  • 浙江省

  • 温州市
  • 浙江省

  • 湖州市
  • 浙江省

  • 绍兴市
  • 浙江省

  • 舟山市
  • 浙江省

  • 衢州市
  • 浙江省

  • 金华市
  • 海南省

  • 三亚市
  • 海南省

  • 三沙市
  • 海南省

  • 儋州市
  • 海南省

  • 海口市
  • 海南省

  • 省直辖县级行政区划
  • 湖北省

  • 十堰市
  • 湖北省

  • 咸宁市
  • 湖北省

  • 孝感市
  • 湖北省

  • 宜昌市
  • 湖北省

  • 恩施土家族苗族自治州
  • 湖北省

  • 武汉市
  • 湖北省

  • 省直辖县级行政区划
  • 湖北省

  • 荆州市
  • 湖北省

  • 荆门市
  • 湖北省

  • 襄阳市
  • 湖北省

  • 鄂州市
  • 湖北省

  • 随州市
  • 湖北省

  • 黄冈市
  • 湖北省

  • 黄石市
  • 湖南省

  • 娄底市
  • 湖南省

  • 岳阳市
  • 湖南省

  • 常德市
  • 湖南省

  • 张家界市
  • 湖南省

  • 怀化市
  • 湖南省

  • 株洲市
  • 湖南省

  • 永州市
  • 湖南省

  • 湘潭市
  • 湖南省

  • 湘西土家族苗族自治州
  • 湖南省

  • 益阳市
  • 湖南省

  • 衡阳市
  • 湖南省

  • 邵阳市
  • 湖南省

  • 郴州市
  • 湖南省

  • 长沙市
  • 甘肃省

  • 临夏回族自治州
  • 甘肃省

  • 兰州市
  • 甘肃省

  • 嘉峪关市
  • 甘肃省

  • 天水市
  • 甘肃省

  • 定西市
  • 甘肃省

  • 平凉市
  • 甘肃省

  • 庆阳市
  • 甘肃省

  • 张掖市
  • 甘肃省

  • 武威市
  • 甘肃省

  • 甘南藏族自治州
  • 甘肃省

  • 白银市
  • 甘肃省

  • 酒泉市
  • 甘肃省

  • 金昌市
  • 甘肃省

  • 陇南市
  • 福建省

  • 三明市
  • 福建省

  • 南平市
  • 福建省

  • 厦门市
  • 福建省

  • 宁德市
  • 福建省

  • 泉州市
  • 福建省

  • 漳州市
  • 福建省

  • 福州市
  • 福建省

  • 莆田市
  • 福建省

  • 龙岩市
  • 西藏自治区

  • 山南市
  • 西藏自治区

  • 拉萨市
  • 西藏自治区

  • 日喀则市
  • 西藏自治区

  • 昌都市
  • 西藏自治区

  • 林芝市
  • 西藏自治区

  • 那曲市
  • 西藏自治区

  • 阿里地区
  • 贵州省

  • 六盘水市
  • 贵州省

  • 安顺市
  • 贵州省

  • 毕节市
  • 贵州省

  • 贵阳市
  • 贵州省

  • 遵义市
  • 贵州省

  • 铜仁市
  • 贵州省

  • 黔东南苗族侗族自治州
  • 贵州省

  • 黔南布依族苗族自治州
  • 贵州省

  • 黔西南布依族苗族自治州
  • 辽宁省

  • 丹东市
  • 辽宁省

  • 大连市
  • 辽宁省

  • 抚顺市
  • 辽宁省

  • 朝阳市
  • 辽宁省

  • 本溪市
  • 辽宁省

  • 沈阳市
  • 辽宁省

  • 盘锦市
  • 辽宁省

  • 营口市
  • 辽宁省

  • 葫芦岛市
  • 辽宁省

  • 辽阳市
  • 辽宁省

  • 铁岭市
  • 辽宁省

  • 锦州市
  • 辽宁省

  • 阜新市
  • 辽宁省

  • 鞍山市
  • 重庆市

  • 重庆市

  • 市辖区
  • 陕西省

  • 咸阳市
  • 陕西省

  • 商洛市
  • 陕西省

  • 安康市
  • 陕西省

  • 宝鸡市
  • 陕西省

  • 延安市
  • 陕西省

  • 榆林市
  • 陕西省

  • 汉中市
  • 陕西省

  • 渭南市
  • 陕西省

  • 西安市
  • 陕西省

  • 铜川市
  • 青海省

  • 果洛藏族自治州
  • 青海省

  • 海东市
  • 青海省

  • 海北藏族自治州
  • 青海省

  • 海南藏族自治州
  • 青海省

  • 海西蒙古族藏族自治州
  • 青海省

  • 玉树藏族自治州
  • 青海省

  • 西宁市
  • 青海省

  • 黄南藏族自治州
  • 黑龙江省

  • 七台河市
  • 黑龙江省

  • 伊春市
  • 黑龙江省

  • 佳木斯市
  • 黑龙江省

  • 双鸭山市
  • 黑龙江省

  • 哈尔滨市
  • 黑龙江省

  • 大兴安岭地区
  • 黑龙江省

  • 大庆市
  • 黑龙江省

  • 牡丹江市
  • 黑龙江省

  • 绥化市
  • 黑龙江省

  • 鸡西市
  • 黑龙江省

  • 鹤岗市
  • 黑龙江省

  • 黑河市
  • 黑龙江省

  • 齐齐哈尔市