前言
斷點上傳功能在移動應用中較爲常見,使用過程中,要求錄製較爲清晰切大小適中的語音文件,能夠控制斷點上傳會有較好的用戶體驗, 下面是我在這方面的一些實踐經驗,分享一下,不成熟的地方歡迎指正!
混合應用中的音頻錄製
首先創建一個Cordova項目:
cordova create Audio com.delaware.AudioDemo AudioDemo
cd Audio
cordova platform add ios
cordova platform add android
添加語音功能插件:
cordova plugin add cordova-media-with-compression
採用的音頻格式爲MPEG4, MPEG4是一個影音串流視訊壓縮技術及商業標準格式,MPEG4之優勢在於其壓縮比(最大可達4000:1),低位元速率,較少之核心程式空間,加強運算功能,及強大之通訊應用整合能力,己成爲影音數位視訊產業,最重要之功及標準格式, 後綴名字爲.m4a
利用插件可以合理進行圖片,比如可以設置壓縮碼率等等,具體方案我們看一實現代碼:
錄音:
// Record audio with compression
//
function recordCompressedAudio() {
var src = "myrecording.m4a";
var mediaRec = new Media(src,
// success callback
function() {
console.log("recordCompressedAudio():Audio Success");
},
// error callback
function(err) {
console.log("recordCompressedAudio():Audio Error: "+ err.code);
});
// Record MPEG compressed audio, single channel at 16kHz
var options = {
SampleRate: 16000,
NumberOfChannels: 1
}
mediaRec.startRecordWithCompression(options);
}
停止錄製:
media.pauseRecord();
播放:(想要播放一個文件,需要先把錄音release掉,否則無法播放)
// Play audio
//
function playAudio(url) {
// Play the audio file at url
var my_media = new Media(url,
// success callback
function() {
console.log("playAudio():Audio Success");
},
// error callback
function(err) {
console.log("playAudio():Audio Error: "+err);
}
);
// Play audio
my_media.play();
// Pause after 10 seconds
setTimeout(function() {
my_media.stop();
}, 10000);
}
對於音頻文件錄製,需要建一個標準文件夾用於管理文件位置,方便。
這裏我們用到插件:
cordova plugin add cordova-plugin-file
定義一個文件夾:
fileSystem.root.getDirectory("MyApp", {create: true}, gotDir);
function gotDir(dirEntry) {
dirEntry.getFile(escape(fileName).replace(/%/g, ''), {create: true, exclusive: false}, gotFileEntry, fail);
}
function gotFileEntry(fileEntry) {
$timeout(function(){
fileEntry.getMetadata(function(data){
if(data.size === 0){
fileUrl = fileEntry.toURL();
}else{
fileUrl = fileEntry.toURL();
}
},function(){
fileUrl = fileEntry.toURL();
});
},200);
}
判斷文件是否存在,沒有的話,進行創建操作。
音頻文件斷點上傳
文件上傳操作
優點:
1.傳輸數據爲字節級,傳輸數據可自定義,數據量小。相應的移動端開發,手機費用低
2.傳輸數據時間短,性能高
3.適合C/S之間信息實時交互
4.可以加密,數據安全性高
缺點:
1.需要對傳輸的數據進行解析,轉化爲應用級的數據
2.對開發人員的開發水平要求高
3.相對於Http協議傳輸,增加了開發量
Http請求主要有http協議,基於http協議的soap協議,常見的http數據請求方式有get和post,web服務
優點:
1.基於應用級的接口使用方便
2.要求的開發水平不高,容錯性強
缺點:
1.傳輸速度慢,數據包大。
2.如實現實時交互,服務器性能壓力大
3.數據傳輸安全性差
Socket適用場景:大文件上傳,網絡遊戲,銀行交互,支付。
這裏有Android爲例:
try {
uploadbar.setMax((int)uploadFile.length());
String souceid = logService.getBindId(uploadFile);
String head = "Content-Length="+ uploadFile.length() + ";filename="+ uploadFile.getName() + ";sourceid="+
(souceid==null? "" : souceid)+"\r\n";
Socket socket = new Socket("172.19.34.69",7878);
OutputStream outStream = socket.getOutputStream();
outStream.write(head.getBytes());
PushbackInputStream inStream = new PushbackInputStream(socket.getInputStream());
String response = StreamTool.readLine(inStream);
String[] items = response.split(";");
String responseid = items[0].substring(items[0].indexOf("=")+1);
String position = items[1].substring(items[1].indexOf("=")+1);
if(souceid==null){
logService.save(responseid, uploadFile);
}
RandomAccessFile fileOutStream = new RandomAccessFile(uploadFile, "r");
fileOutStream.seek(Integer.valueOf(position));
byte[] buffer = new byte[1024];
int len = -1;
int length = Integer.valueOf(position);
while(start&&(len = fileOutStream.read(buffer)) != -1){
outStream.write(buffer, 0, len);
length += len;
Message msg = new Message();
msg.getData().putInt("size", length);
handler.sendMessage(msg);
}
fileOutStream.close();
outStream.close();
inStream.close();
socket.close();
if(length==uploadFile.length()) logService.delete(uploadFile);
} catch (Exception e) {
e.printStackTrace();
}
在Android中除了通過http協議上傳小文件外,還可以通過Socket上傳較大的文件
案例具體思路:
文件被第一次上傳時發送: “Content-Length=”+ uploadFile.length() + “;filename=”+ uploadFile.getName() + “;sourceid=”+null+”\r\n”;字段給服務器
服務器收到字段後,看到文件的sourceid字段值爲空,則表示該文件第一次上傳,服務器就會自動爲其創建id,並且在本地根據文件名建立相應文件用於接收文件數據,同時把該文件路徑和id保存在Map集合中,併發送:“sourceid=”+ id+ “;position=0\r\n”;內容給客戶端,客戶端收到服務器爲其創建的id和應該從上傳文件的什麼位置開始讀取信息後,在SQLite數據庫中記錄下本次上傳文件的id和文件路徑,然後上傳文件。
服務器端則開始接收從客戶端發來的數據並保存起來,並且時刻把該文件的上傳的數據大小保存在以該文件命名的.log文件中。
當在發送的的時候突然關機或網絡出現狀況,當再次上傳該文件時,客戶端就會從SQLite中根據文件路徑查找到已上傳文件的id,然後發送內容給服務器端,服務器從發來的sourceid字段中讀到了數據,就從map集合中找到該文件路徑,然後根據路徑和文件名找到.log文件,並從中讀取上次上傳文件的大小發送給客戶端,客戶端得到後遍選擇從文件的指定文件讀取上傳,服務器則再次接收並從文件指定位置保存。
Socket套接字原理分析
建立Socket連接至少需要一對套接字,其中一個運行於客戶端,稱爲ClientSocket ,另一個運行於服務器端,稱爲ServerSocket 。
套接字之間的連接過程分爲三個步驟:服務器監聽,客戶端請求,連接確認。
服務器監聽:
服務器端套接字並不定位具體的客戶端套接字,而是處於等待連接的狀態,實時監控網絡狀態,等待客戶端的連接請求。
客戶端請求:
指客戶端的套接字提出連接請求,要連接的目標是服務器端的套接字。爲此,客戶端的套接字必須首先描述它要連接的服務器的套接字,指出服務器端套接字的地址和端口號,然後就向服務器端套接字提出連接請求。
連接確認:
當服務器端套接字監聽到或者說接收到客戶端套接字的連接請求時,就響應客戶端套接字的請求,建立一個新的線程,把服務器端套接字的描述發給客戶端,一旦客戶端確認了此描述,雙方就正式建立連接。而服務器端套接字繼續處於監聽狀態,繼續接收其他客戶端套接字的連接請求。
參考文獻:http://blog.csdn.net/shimiso/article/details/8529633
http://blog.csdn.net/zl594389970/article/details/12500371