最近在做一个小网站,其中有一个语音识别的功能,我暂时打算用Google Speech API来实现,但是在这之前还有一个小问题那就是录音。要在网页中录音应该大多数是通过Flash或者java applet实现的,因为考虑到flash比较普及,我觉得采用flash。因为我本身不会flash actionscript那些,想在网上找个现成,功夫不负有心人终于让我找到了这个FlashWavRecorder。其github地址为:https://github.com/cykod/FlashWavRecorder
这个项目你一个有两文件夹flash和html,flash文件夹中是文件,html文件夹中是一个示例,试了一下果然能录音。
但是上传却出了问题,卡在save_progress了。
找了一会儿原因,发现是接受上传文件的upload.php有个小问题,他的<? 后面没有php导致直接把所有代码当文本返回了。改完之后如下:
<?php $save_folder = dirname(__FILE__) . "/audio"; if(! file_exists($save_folder)) { if(! mkdir($save_folder)) {
首先下面的配置对我来说并不需要,我把它直接删了,但是问题就出现了。
发生这个问题的原因是index.html 中有一段js脚本
$(function() { var gain = $('#gain')[0]; var silenceLevel = $('#silenceLevel')[0]; for(var i=0; i<=100; i++) { gain.options[gain.options.length] = new Option(100-i); silenceLevel.options[silenceLevel.options.length] = new Option(i); } var appWidth = 24; var appHeight = 24; var flashvars = {'event_handler': 'microphone_recorder_events', 'upload_image': 'images/upload.png'}; var params = {}; var attributes = {'id': "recorderApp", 'name': "recorderApp"}; swfobject.embedSWF("recorder.swf", "flashcontent", appWidth, appHeight, "11.0.0", "", flashvars, params, attributes); });
因为我把配置的表单删掉了,所以$(‘#gain’)[0]和$(‘#silenceLevel’)[0]都是undefined的,对它们进行操作报错脚本终止导致flash没有成功加载,把那下面这5行删掉即可。
var gain = $('#gain')[0]; var silenceLevel = $('#silenceLevel')[0]; for(var i=0; i<=100; i++) { gain.options[gain.options.length] = new Option(100-i); silenceLevel.options[silenceLevel.options.length] = new Option(i); }
总的来说这个东西就是js调用flash的js接口,flash里再调用js与页面交互。
位于recorder.js文件的microphone_recorder_events函数就是处理flash返回状态的函数。
通过修改这个函数可以修改flash不同状态事页面的显示。
因为这个flash每次刷新页面后都要点一下录音按键后允许flash使用麦克风才行,我想省掉要先点录音按键这一步,页面刷新有自动弹出麦克风请求窗口。其实只要还microphone_recorder_events中case “ready” 这个分支的最后加一行Recorder.record(‘audio’, ‘audio.wav’);即可,因为点击那个红色的录音键实际上也是执行了这句脚本。
case "ready": var width = parseInt(arguments[1]); var height = parseInt(arguments[2]); Recorder.uploadFormId = "#uploadForm"; Recorder.uploadFieldName = "upload_file[filename]"; Recorder.connect("recorderApp", 0); Recorder.recorderOriginalWidth = width; Recorder.recorderOriginalHeight = height; $('#play_button').css({'margin-left': width + 8}); $('#save_button').css({'width': width, 'height': height}); Recorder.record('audio', 'audio.wav'); //在示例中改成$("#record_button").click();也行 break;
最后我想实现停止录音后直接上传该怎么修改呢?
这个上传按键并不是一个html元素,而是在flash中的,这意味着我不得不去修改flash了。
flash文件夹下有4个as文件,因为只是要改一小点我就直接看RecorderJSInterface.as这个文件了,果然和文件名一样这个文件定义了js调用的入口,还有通过ExternalInterface.call(methodName: String, [parameter1: Object]) : Object 方法调用页面中的js。
话不多说,我在这个文件中找到两个关键的方法record(name:String, filename:String=null):Boolean 和 save():Boolean 一个是录音是调用的,第二个是保存(就是上传服务器)时调用的。这样在record中停止录音的语句后调用sava方法即可,修改后如下:
public function record(name:String, filename:String=null):Boolean { if(! this.isMicrophoneAvailable()) { return false; } if(this.recorder.recording) { this.recorder.stop(); ExternalInterface.call(this.eventHandler, RecorderJSInterface.RECORDING_STOPPED, this.recorder.currentSoundName, this.recorder.duration()); this.save(); //加入这句 } else { this.recorder.record(name, filename); ExternalInterface.call(this.eventHandler, RecorderJSInterface.RECORDING, this.recorder.currentSoundName); } return this.recorder.recording; }
接下来就是编译它了,先去下载sdk,下载地址为http://www.adobe.com/devnet/flex/flex-sdk-download-all.html
下载完成后把其中的bin目录加入环境变量PATH,打开命令行到刚刚的flash目录执行下面语句。
mxmlc Recorder.as -output recorder.swf
把生成的recorder.swf覆盖html中的,刷新页面,虽然停止录音后进行了保存但是出现了异常
但是再点击上传按钮却能成功上传,我检查代码,发现是执行URLLoader.load(request:URLRequest):void时发生了异常,推测是出于安全问题,只能通过用户交互来调用。那我们就来再改一下吧。
先把recorder.as里的ready方法和save()方法改一下,改成下面这样:
public function ready():void { addChild(saveButton); recorderInterface.saveButton = saveButton; saveButton.addEventListener(MouseEvent.MOUSE_UP, mouseReleased); recorderInterface.ready(saveButton.width, saveButton.height); } public function save():void { recorderInterface.record("audio", "audio.wav"); }
再把RecorderJSInterface.as里show()和hide()方法的函数体变成空的,如下:
public function show():void { } public function hide():void { }
再编译一下搞定,直接点上传键就录音加上传一条龙了。