├── .settings ├── org.eclipse.wst.jsdt.ui.superType.name ├── org.eclipse.wst.jsdt.ui.superType.container ├── org.eclipse.wst.common.project.facet.core.xml ├── org.eclipse.jdt.core.prefs ├── .jsdtscope └── org.eclipse.wst.common.component ├── WebRoot ├── META-INF │ └── MANIFEST.MF ├── favicon.ico ├── WUI │ └── qrecord │ │ ├── recorder.swf │ │ ├── images │ │ ├── pause.png │ │ ├── play.png │ │ ├── stop.png │ │ ├── record.png │ │ └── upload.png │ │ ├── style.css │ │ └── js │ │ ├── main.js │ │ ├── recorder.js │ │ └── swfobject.js └── WEB-INF │ ├── lib │ ├── commons-io-2.4.jar │ ├── cos-26Dec2008.jar │ ├── freemarker-2.3.20.jar │ ├── commons-fileupload-1.3.1.jar │ └── jfinal-1.9-bin-with-src-render.jar │ ├── classes │ └── com │ │ └── demo │ │ ├── MyConfig.class │ │ └── index │ │ └── IndexController.class │ ├── web.xml │ └── view │ └── index.html ├── .mymetadata ├── .classpath ├── README.md ├── src └── com │ └── demo │ ├── MyConfig.java │ └── index │ └── IndexController.java ├── LICENSE └── .project /.settings/org.eclipse.wst.jsdt.ui.superType.name: -------------------------------------------------------------------------------- 1 | Window -------------------------------------------------------------------------------- /WebRoot/META-INF/MANIFEST.MF: -------------------------------------------------------------------------------- 1 | Manifest-Version: 1.0 2 | Class-Path: 3 | 4 | -------------------------------------------------------------------------------- /.settings/org.eclipse.wst.jsdt.ui.superType.container: -------------------------------------------------------------------------------- 1 | org.eclipse.wst.jsdt.launching.baseBrowserLibrary -------------------------------------------------------------------------------- /WebRoot/favicon.ico: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/uikoo9/recorder-online-upload/HEAD/WebRoot/favicon.ico -------------------------------------------------------------------------------- /WebRoot/WUI/qrecord/recorder.swf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/uikoo9/recorder-online-upload/HEAD/WebRoot/WUI/qrecord/recorder.swf -------------------------------------------------------------------------------- /WebRoot/WUI/qrecord/images/pause.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/uikoo9/recorder-online-upload/HEAD/WebRoot/WUI/qrecord/images/pause.png -------------------------------------------------------------------------------- /WebRoot/WUI/qrecord/images/play.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/uikoo9/recorder-online-upload/HEAD/WebRoot/WUI/qrecord/images/play.png -------------------------------------------------------------------------------- /WebRoot/WUI/qrecord/images/stop.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/uikoo9/recorder-online-upload/HEAD/WebRoot/WUI/qrecord/images/stop.png -------------------------------------------------------------------------------- /WebRoot/WEB-INF/lib/commons-io-2.4.jar: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/uikoo9/recorder-online-upload/HEAD/WebRoot/WEB-INF/lib/commons-io-2.4.jar -------------------------------------------------------------------------------- /WebRoot/WEB-INF/lib/cos-26Dec2008.jar: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/uikoo9/recorder-online-upload/HEAD/WebRoot/WEB-INF/lib/cos-26Dec2008.jar -------------------------------------------------------------------------------- /WebRoot/WUI/qrecord/images/record.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/uikoo9/recorder-online-upload/HEAD/WebRoot/WUI/qrecord/images/record.png -------------------------------------------------------------------------------- /WebRoot/WUI/qrecord/images/upload.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/uikoo9/recorder-online-upload/HEAD/WebRoot/WUI/qrecord/images/upload.png -------------------------------------------------------------------------------- /WebRoot/WEB-INF/lib/freemarker-2.3.20.jar: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/uikoo9/recorder-online-upload/HEAD/WebRoot/WEB-INF/lib/freemarker-2.3.20.jar -------------------------------------------------------------------------------- /WebRoot/WEB-INF/classes/com/demo/MyConfig.class: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/uikoo9/recorder-online-upload/HEAD/WebRoot/WEB-INF/classes/com/demo/MyConfig.class -------------------------------------------------------------------------------- /WebRoot/WEB-INF/lib/commons-fileupload-1.3.1.jar: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/uikoo9/recorder-online-upload/HEAD/WebRoot/WEB-INF/lib/commons-fileupload-1.3.1.jar -------------------------------------------------------------------------------- /WebRoot/WEB-INF/lib/jfinal-1.9-bin-with-src-render.jar: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/uikoo9/recorder-online-upload/HEAD/WebRoot/WEB-INF/lib/jfinal-1.9-bin-with-src-render.jar -------------------------------------------------------------------------------- /WebRoot/WEB-INF/classes/com/demo/index/IndexController.class: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/uikoo9/recorder-online-upload/HEAD/WebRoot/WEB-INF/classes/com/demo/index/IndexController.class -------------------------------------------------------------------------------- /.settings/org.eclipse.wst.common.project.facet.core.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | -------------------------------------------------------------------------------- /.mymetadata: -------------------------------------------------------------------------------- 1 | 2 | 9 | 10 | 11 | 12 | 13 | 14 | -------------------------------------------------------------------------------- /.settings/org.eclipse.jdt.core.prefs: -------------------------------------------------------------------------------- 1 | eclipse.preferences.version=1 2 | org.eclipse.jdt.core.compiler.codegen.inlineJsrBytecode=enabled 3 | org.eclipse.jdt.core.compiler.codegen.targetPlatform=1.6 4 | org.eclipse.jdt.core.compiler.compliance=1.6 5 | org.eclipse.jdt.core.compiler.problem.assertIdentifier=error 6 | org.eclipse.jdt.core.compiler.problem.enumIdentifier=error 7 | org.eclipse.jdt.core.compiler.source=1.6 8 | -------------------------------------------------------------------------------- /.settings/.jsdtscope: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | -------------------------------------------------------------------------------- /.classpath: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | -------------------------------------------------------------------------------- /.settings/org.eclipse.wst.common.component: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | -------------------------------------------------------------------------------- /WebRoot/WEB-INF/web.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | jfinal 5 | com.jfinal.core.JFinalFilter 6 | 7 | configClass 8 | com.demo.MyConfig 9 | 10 | 11 | 12 | jfinal 13 | /* 14 | 15 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # recorder-online-upload 2 | 3 | ## 简介 4 | 1. 在线录音并直接上传到服务器 5 | 2. 封装了[FlashWavRecorder](https://github.com/cykod/FlashWavRecorder) 6 | 7 | ## 使用 8 | 1. 运行 9 | 1. 请下载本项目,并导入myeclipse中 10 | 2. 跑起项目,访问http://localhost:8080/recorder-online-upload查看效果 11 | 2. 定制 12 | 1. 打开WEB-INF/view/index.html 13 | 2. 只有两段html注释中的代码是需要的 14 | 3. 将上面代码中的${base}替换成自己项目的路径 15 | 4. 将上面代码中form的action替换成自己的上传文件处理action 16 | 5. 将main.js中一些base路径替换为自己对应的路径 17 | 18 | ## 详细说明 19 | 详细说明请访问这里[http://uikoo9.com/blog/detail/java-flashwavrecorder-new](http://uikoo9.com/blog/detail/java-flashwavrecorder-new) 20 | 21 | ## 作者 22 | 1. uikoo9 23 | 2. 欢迎访问[uikoo9.com](http://uikoo9.com) 24 | 25 | ## 捐助 26 | 希望得到您的捐助: 27 | 28 | (支付宝捐助) 29 | 30 | ![zhifubao](http://uikoo9.qiniudn.com/@/img/donate/zhifu2.png) 31 | 32 | (微信捐助) 33 | 34 | ![weixin](http://uikoo9.qiniudn.com/@/img/donate/zhifu1.png) 35 | -------------------------------------------------------------------------------- /src/com/demo/MyConfig.java: -------------------------------------------------------------------------------- 1 | package com.demo; 2 | 3 | import com.demo.index.IndexController; 4 | import com.jfinal.config.Constants; 5 | import com.jfinal.config.Handlers; 6 | import com.jfinal.config.Interceptors; 7 | import com.jfinal.config.JFinalConfig; 8 | import com.jfinal.config.Plugins; 9 | import com.jfinal.config.Routes; 10 | 11 | /** 12 | * API引导式配置 13 | */ 14 | public class MyConfig extends JFinalConfig { 15 | 16 | /** 17 | * 配置常量 18 | */ 19 | public void configConstant(Constants me) { 20 | me.setDevMode(true); 21 | } 22 | 23 | /** 24 | * 配置路由 25 | */ 26 | public void configRoute(Routes me) { 27 | me.add("/", IndexController.class); 28 | } 29 | 30 | public void configPlugin(Plugins me) {} 31 | public void configInterceptor(Interceptors me) {} 32 | public void configHandler(Handlers me) {} 33 | public static void main(String[] args) {} 34 | } 35 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | The MIT License (MIT) 2 | 3 | Copyright (c) 2015 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | 23 | -------------------------------------------------------------------------------- /src/com/demo/index/IndexController.java: -------------------------------------------------------------------------------- 1 | package com.demo.index; 2 | 3 | import java.io.File; 4 | import java.util.Iterator; 5 | 6 | import javax.servlet.http.HttpServletRequest; 7 | 8 | import org.apache.commons.fileupload.FileItem; 9 | import org.apache.commons.fileupload.disk.DiskFileItemFactory; 10 | import org.apache.commons.fileupload.servlet.ServletFileUpload; 11 | 12 | import com.jfinal.core.Controller; 13 | 14 | public class IndexController extends Controller { 15 | public void index() { 16 | setAttr("base", getHttpPath(getRequest())); 17 | render("/WEB-INF/view/index.html"); 18 | } 19 | private String getHttpPath(HttpServletRequest request){ 20 | StringBuilder path = new StringBuilder(); 21 | 22 | path.append(request.getScheme() + "://"); 23 | path.append(request.getServerName() + ":"); 24 | path.append(request.getServerPort()); 25 | path.append(request.getContextPath()); 26 | 27 | return path.toString(); 28 | } 29 | 30 | /** 31 | * 在线上传音频示例 32 | * @throws Exception 33 | */ 34 | public void upload() throws Exception{ 35 | Iterator iter = new ServletFileUpload(new DiskFileItemFactory()).parseRequest(getRequest()).iterator(); 36 | while (iter.hasNext()) { 37 | FileItem item = iter.next(); 38 | 39 | if(!item.isFormField()){ 40 | // 保存文件,简单的保存到本地,可以自行修改 41 | item.write(new File("d://" + item.getName())); 42 | } 43 | } 44 | 45 | // 返回值,1是成功 46 | renderJson("{\"saved\": 1}"); 47 | } 48 | 49 | } -------------------------------------------------------------------------------- /.project: -------------------------------------------------------------------------------- 1 | 2 | 3 | recorder-online-upload 4 | 5 | 6 | 7 | 8 | 9 | org.eclipse.wst.common.project.facet.core.builder 10 | 11 | 12 | 13 | 14 | org.eclipse.wst.jsdt.core.javascriptValidator 15 | 16 | 17 | 18 | 19 | com.genuitec.eclipse.j2eedt.core.WebClasspathBuilder 20 | 21 | 22 | 23 | 24 | org.eclipse.jdt.core.javabuilder 25 | 26 | 27 | 28 | 29 | com.genuitec.eclipse.j2eedt.core.J2EEProjectValidator 30 | 31 | 32 | 33 | 34 | com.genuitec.eclipse.j2eedt.core.DeploymentDescriptorValidator 35 | 36 | 37 | 38 | 39 | org.eclipse.wst.validation.validationbuilder 40 | 41 | 42 | 43 | 44 | 45 | org.eclipse.jem.workbench.JavaEMFNature 46 | com.genuitec.eclipse.j2eedt.core.webnature 47 | org.eclipse.jdt.core.javanature 48 | org.eclipse.wst.jsdt.core.jsNature 49 | org.eclipse.wst.common.project.facet.core.nature 50 | org.eclipse.wst.common.modulecore.ModuleCoreNature 51 | 52 | 53 | -------------------------------------------------------------------------------- /WebRoot/WUI/qrecord/style.css: -------------------------------------------------------------------------------- 1 | h1 a { 2 | color: red; 3 | text-decoration: none; 4 | } 5 | 6 | .qcontainer { 7 | width: 400px; 8 | margin: 50px auto; 9 | background-color: #f4f4f4; 10 | padding: 30px; 11 | font-family: sans-serif; 12 | font-size: 14px; 13 | border-radius: 22px; 14 | } 15 | 16 | .control_panel { 17 | white-space: nowrap; 18 | padding: 0; 19 | margin: 2px; 20 | vertical-align: middle; 21 | height: 24px; 22 | background-color: #e7e7e7; 23 | position: relative; 24 | } 25 | 26 | .control_panel a { 27 | outline: none; 28 | display: inline-block; 29 | width: 24px; 30 | height: 24px; 31 | text-decoration: none; 32 | } 33 | 34 | .control_panel a img { 35 | border: 0; 36 | padding: 0; 37 | margin: 0; 38 | } 39 | 40 | .control_panel .level { 41 | position: absolute; 42 | right: 0; 43 | top: 0; 44 | bottom: 0; 45 | background: linear-gradient(to right, #8bb300 0%, #3b9d00 100%); 46 | } 47 | 48 | .details { 49 | font-size: 12px; 50 | } 51 | 52 | #save_button { 53 | padding: 0; 54 | margin: 0; 55 | } 56 | 57 | .play_button { 58 | display: inline-block; 59 | } 60 | 61 | .pause_button { 62 | display: inline-block; 63 | } 64 | 65 | .mic_config ul, .mic_config li { 66 | list-style: none; 67 | margin: 0; 68 | padding: 0; 69 | font-size: 12px 70 | } 71 | 72 | #recorderApp { 73 | position: relative; 74 | } 75 | 76 | .control_panel button { 77 | width: 24px; 78 | height: 24px; 79 | padding: 2px 0 0 0; 80 | } 81 | 82 | .control_panel button img { 83 | width: 16px; 84 | height: 16px; 85 | } 86 | 87 | .control_panel.idle .stop_recording_button, 88 | .control_panel.idle .play_button, 89 | .control_panel.idle .pause_playing_button, 90 | .control_panel.idle .stop_playing_button, 91 | .control_panel.recording .record_button, 92 | .control_panel.recording .play_button, 93 | .control_panel.recording .pause_playing_button, 94 | .control_panel.recording .stop_playing_button, 95 | .control_panel.playback_ready .stop_recording_button, 96 | .control_panel.playback_ready .pause_playing_button, 97 | .control_panel.playback_ready .stop_playing_button, 98 | .control_panel.playing .stop_recording_button, 99 | .control_panel.playing .play_button, 100 | .control_panel.playback_paused .stop_recording_button, 101 | .control_panel.playback_paused .pause_playing_button { 102 | display: none; 103 | } -------------------------------------------------------------------------------- /WebRoot/WUI/qrecord/js/main.js: -------------------------------------------------------------------------------- 1 | $(function () { 2 | var $uploadStatus = $('#upload_status'), 3 | $showLevelButton = $('.show_level'), 4 | $hideLevelButton = $('.hide_level'), 5 | $level = $('.control_panel .level'); 6 | 7 | var CLASS_CONTROLS = "control_panel"; 8 | var CLASS_RECORDING = "recording"; 9 | var CLASS_PLAYBACK_READY = "playback_ready"; 10 | var CLASS_PLAYING = "playing"; 11 | var CLASS_PLAYBACK_PAUSED = "playback_paused"; 12 | 13 | // Embedding flash object --------------------------------------------------------------------------------------------- 14 | 15 | var appWidth = 24; 16 | var appHeight = 24; 17 | var flashvars = {'upload_image': base + '/WUI/qrecord/images/upload.png'}; 18 | var params = {}; 19 | var attributes = {'id': "recorderApp", 'name': "recorderApp"}; 20 | swfobject.embedSWF(base + "/WUI/qrecord//recorder.swf", "flashcontent", appWidth, appHeight, "11.0.0", "", flashvars, params, attributes); 21 | 22 | // Handling FWR events ------------------------------------------------------------------------------------------------ 23 | 24 | window.fwr_event_handler = function fwr_event_handler() { 25 | $('#status').text("最后的录音事件:" + arguments[0]); 26 | var name, $controls; 27 | switch (arguments[0]) { 28 | case "ready": 29 | var width = parseInt(arguments[1]); 30 | var height = parseInt(arguments[2]); 31 | FWRecorder.uploadFormId = "#uploadForm"; 32 | FWRecorder.uploadFieldName = "upload_file[filename]"; 33 | FWRecorder.connect("recorderApp", 0); 34 | FWRecorder.recorderOriginalWidth = width; 35 | FWRecorder.recorderOriginalHeight = height; 36 | $('.save_button').css({'width': width, 'height': height}); 37 | break; 38 | 39 | case "no_microphone_found": 40 | break; 41 | 42 | case "microphone_user_request": 43 | recorderEl().addClass("floating"); 44 | FWRecorder.showPermissionWindow(); 45 | break; 46 | 47 | case "microphone_connected": 48 | FWRecorder.isReady = true; 49 | $uploadStatus.css({'color': '#000'}); 50 | break; 51 | 52 | case "permission_panel_closed": 53 | FWRecorder.defaultSize(); 54 | recorderEl().removeClass("floating"); 55 | break; 56 | 57 | case "recording": 58 | name = arguments[1]; 59 | $controls = controlsEl(name); 60 | FWRecorder.hide(); 61 | setControlsClass($controls, CLASS_RECORDING); 62 | break; 63 | 64 | case "recording_stopped": 65 | name = arguments[1]; 66 | $controls = controlsEl(name); 67 | var duration = arguments[2]; 68 | FWRecorder.show(); 69 | setControlsClass($controls, CLASS_PLAYBACK_READY); 70 | $('#duration').text(duration.toFixed(4) + " seconds"); 71 | break; 72 | 73 | case "microphone_level": 74 | $level.css({width: arguments[1] * 50 + '%'}); 75 | break; 76 | 77 | case "observing_level": 78 | $showLevelButton.hide(); 79 | $hideLevelButton.show(); 80 | break; 81 | 82 | case "observing_level_stopped": 83 | $showLevelButton.show(); 84 | $hideLevelButton.hide(); 85 | $level.css({width: 0}); 86 | break; 87 | 88 | case "playing": 89 | name = arguments[1]; 90 | $controls = controlsEl(name); 91 | setControlsClass($controls, CLASS_PLAYING); 92 | break; 93 | 94 | case "playback_started": 95 | name = arguments[1]; 96 | var latency = arguments[2]; 97 | break; 98 | 99 | case "stopped": 100 | name = arguments[1]; 101 | $controls = controlsEl(name); 102 | setControlsClass($controls, CLASS_PLAYBACK_READY); 103 | break; 104 | 105 | case "playing_paused": 106 | name = arguments[1]; 107 | $controls = controlsEl(name); 108 | setControlsClass($controls, CLASS_PLAYBACK_PAUSED); 109 | break; 110 | 111 | case "save_pressed": 112 | FWRecorder.updateForm(); 113 | break; 114 | 115 | case "saving": 116 | name = arguments[1]; 117 | break; 118 | 119 | case "saved": 120 | name = arguments[1]; 121 | var data = $.parseJSON(arguments[2]); 122 | if (data.saved) { 123 | $('#upload_status').css({'color': '#0F0'}).text(name + " was saved"); 124 | $('#qrecordId').val(data.id); 125 | } else { 126 | $('#upload_status').css({'color': '#F00'}).text(name + " was not saved"); 127 | } 128 | break; 129 | 130 | case "save_failed": 131 | name = arguments[1]; 132 | var errorMessage = arguments[2]; 133 | $uploadStatus.css({'color': '#F00'}).text(name + " failed: " + errorMessage); 134 | break; 135 | 136 | case "save_progress": 137 | name = arguments[1]; 138 | var bytesLoaded = arguments[2]; 139 | var bytesTotal = arguments[3]; 140 | $uploadStatus.css({'color': '#000'}).text(name + " progress: " + bytesLoaded + " / " + bytesTotal); 141 | break; 142 | } 143 | }; 144 | 145 | // Helper functions --------------------------------------------------------------------------------------------------- 146 | 147 | function setControlsClass($controls, className) { 148 | $controls.attr('class', CLASS_CONTROLS + ' ' + className); 149 | } 150 | 151 | function controlsEl(name) { 152 | return $('#recorder-' + name); 153 | } 154 | 155 | function recorderEl() { 156 | return $('#recorderApp'); 157 | } 158 | 159 | 160 | // Button actions ----------------------------------------------------------------------------------------------------- 161 | 162 | window.microphonePermission = function () { 163 | recorderEl().addClass("floating"); 164 | FWRecorder.showPermissionWindow({permanent: true}); 165 | }; 166 | 167 | window.configureMicrophone = function () { 168 | if (!FWRecorder.isReady) { 169 | return; 170 | } 171 | FWRecorder.configure($('#rate').val(), $('#gain').val(), $('#silenceLevel').val(), $('#silenceTimeout').val()); 172 | FWRecorder.setUseEchoSuppression($('#useEchoSuppression').is(":checked")); 173 | FWRecorder.setLoopBack($('#loopBack').is(":checked")); 174 | }; 175 | 176 | }); 177 | -------------------------------------------------------------------------------- /WebRoot/WUI/qrecord/js/recorder.js: -------------------------------------------------------------------------------- 1 | 2 | (function(global) { 3 | var Recorder; 4 | 5 | var RECORDED_AUDIO_TYPE = "audio/wav"; 6 | 7 | Recorder = { 8 | recorder: null, 9 | recorderOriginalWidth: 0, 10 | recorderOriginalHeight: 0, 11 | uploadFormId: null, 12 | uploadFieldName: null, 13 | isReady: false, 14 | 15 | connect: function(name, attempts) { 16 | if(navigator.appName.indexOf("Microsoft") != -1) { 17 | Recorder.recorder = window[name]; 18 | } else { 19 | Recorder.recorder = document[name]; 20 | } 21 | 22 | if(attempts >= 40) { 23 | return; 24 | } 25 | 26 | // flash app needs time to load and initialize 27 | if(Recorder.recorder && Recorder.recorder.init) { 28 | Recorder.recorderOriginalWidth = Recorder.recorder.width; 29 | Recorder.recorderOriginalHeight = Recorder.recorder.height; 30 | if(Recorder.uploadFormId && $) { 31 | var frm = $(Recorder.uploadFormId); 32 | Recorder.recorder.init(frm.attr('action').toString(), Recorder.uploadFieldName, frm.serializeArray()); 33 | } 34 | return; 35 | } 36 | 37 | setTimeout(function() {Recorder.connect(name, attempts+1);}, 100); 38 | }, 39 | 40 | playBack: function(name) { 41 | // TODO: Rename to `playback` 42 | Recorder.recorder.playBack(name); 43 | }, 44 | 45 | pausePlayBack: function(name) { 46 | // TODO: Rename to `pausePlayback` 47 | Recorder.recorder.pausePlayBack(name); 48 | }, 49 | 50 | playBackFrom: function(name, time) { 51 | // TODO: Rename to `playbackFrom` 52 | Recorder.recorder.playBackFrom(name, time); 53 | }, 54 | 55 | record: function(name, filename) { 56 | Recorder.recorder.record(name, filename); 57 | }, 58 | 59 | stopRecording: function() { 60 | Recorder.recorder.stopRecording(); 61 | }, 62 | 63 | stopPlayBack: function() { 64 | // TODO: Rename to `stopPlayback` 65 | Recorder.recorder.stopPlayBack(); 66 | }, 67 | 68 | observeLevel: function() { 69 | Recorder.recorder.observeLevel(); 70 | }, 71 | 72 | stopObservingLevel: function() { 73 | Recorder.recorder.stopObservingLevel(); 74 | }, 75 | 76 | observeSamples: function() { 77 | Recorder.recorder.observeSamples(); 78 | }, 79 | 80 | stopObservingSamples: function() { 81 | Recorder.recorder.stopObservingSamples(); 82 | }, 83 | 84 | resize: function(width, height) { 85 | Recorder.recorder.width = width + "px"; 86 | Recorder.recorder.height = height + "px"; 87 | }, 88 | 89 | defaultSize: function() { 90 | Recorder.resize(Recorder.recorderOriginalWidth, Recorder.recorderOriginalHeight); 91 | }, 92 | 93 | show: function() { 94 | Recorder.recorder.show(); 95 | }, 96 | 97 | hide: function() { 98 | Recorder.recorder.hide(); 99 | }, 100 | 101 | duration: function(name) { 102 | // TODO: rename to `getDuration` 103 | return Recorder.recorder.duration(name || Recorder.uploadFieldName); 104 | }, 105 | 106 | getBase64: function(name) { 107 | var data = Recorder.recorder.getBase64(name); 108 | return 'data:' + RECORDED_AUDIO_TYPE + ';base64,' + data; 109 | }, 110 | 111 | getBlob: function(name) { 112 | var base64Data = Recorder.getBase64(name).split(',')[1]; 113 | return base64toBlob(base64Data, RECORDED_AUDIO_TYPE); 114 | }, 115 | 116 | getCurrentTime: function(name) { 117 | return Recorder.recorder.getCurrentTime(name); 118 | }, 119 | 120 | isMicrophoneAccessible: function() { 121 | return Recorder.recorder.isMicrophoneAccessible(); 122 | }, 123 | 124 | updateForm: function() { 125 | var frm = $(Recorder.uploadFormId); 126 | Recorder.recorder.update(frm.serializeArray()); 127 | }, 128 | 129 | showPermissionWindow: function(options) { 130 | Recorder.resize(240, 160); 131 | // need to wait until app is resized before displaying permissions screen 132 | var permissionCommand = function() { 133 | if (options && options.permanent) { 134 | Recorder.recorder.permitPermanently(); 135 | } else { 136 | Recorder.recorder.permit(); 137 | } 138 | }; 139 | setTimeout(permissionCommand, 1); 140 | }, 141 | 142 | configure: function(rate, gain, silenceLevel, silenceTimeout) { 143 | rate = parseInt(rate || 22); 144 | gain = parseInt(gain || 100); 145 | silenceLevel = parseInt(silenceLevel || 0); 146 | silenceTimeout = parseInt(silenceTimeout || 4000); 147 | switch(rate) { 148 | case 44: 149 | case 22: 150 | case 11: 151 | case 8: 152 | case 5: 153 | break; 154 | default: 155 | throw("invalid rate " + rate); 156 | } 157 | 158 | if(gain < 0 || gain > 100) { 159 | throw("invalid gain " + gain); 160 | } 161 | 162 | if(silenceLevel < 0 || silenceLevel > 100) { 163 | throw("invalid silenceLevel " + silenceLevel); 164 | } 165 | 166 | if(silenceTimeout < -1) { 167 | throw("invalid silenceTimeout " + silenceTimeout); 168 | } 169 | 170 | Recorder.recorder.configure(rate, gain, silenceLevel, silenceTimeout); 171 | }, 172 | 173 | setUseEchoSuppression: function(val) { 174 | if(typeof(val) != 'boolean') { 175 | throw("invalid value for setting echo suppression, val: " + val); 176 | } 177 | 178 | Recorder.recorder.setUseEchoSuppression(val); 179 | }, 180 | 181 | setLoopBack: function(val) { 182 | if(typeof(val) != 'boolean') { 183 | throw("invalid value for setting loop back, val: " + val); 184 | } 185 | 186 | Recorder.recorder.setLoopBack(val); 187 | } 188 | }; 189 | 190 | function base64toBlob(b64Data, contentType, sliceSize) { 191 | contentType = contentType || ''; 192 | sliceSize = sliceSize || 512; 193 | 194 | var byteCharacters = atob(b64Data); 195 | var byteArrays = []; 196 | 197 | for (var offset = 0; offset < byteCharacters.length; offset += sliceSize) { 198 | var slice = byteCharacters.slice(offset, offset + sliceSize); 199 | 200 | var byteNumbers = new Array(slice.length); 201 | for (var i = 0; i < slice.length; i++) { 202 | byteNumbers[i] = slice.charCodeAt(i); 203 | } 204 | 205 | var byteArray = new Uint8Array(byteNumbers); 206 | byteArrays.push(byteArray); 207 | } 208 | 209 | return new Blob(byteArrays, {type: contentType}); 210 | } 211 | 212 | 213 | global.FWRecorder = Recorder; 214 | 215 | 216 | })(this); -------------------------------------------------------------------------------- /WebRoot/WEB-INF/view/index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | uikoo9.com 23 | 24 | 25 | 26 | 27 | 28 | 29 | 30 | 37 | 38 | 39 | 40 | 41 | 42 | 43 | 44 | 45 | 46 | 47 | 48 | 52 | 53 | 54 |
55 | 87 | 88 |
89 |
90 |
91 | 92 | 93 | 94 | 95 | 96 | 97 | 98 |
99 |
100 | 103 | 106 | 109 | 112 | 115 |
116 |
117 | 118 |
119 | 120 | 121 | 122 | 123 | 124 | 125 |
最后的录音事件:ready
126 |
录音时长:
127 |
上传状态:
128 | 129 |
130 | 131 | 132 |
133 | 134 | 135 | 136 |
137 |
138 | 139 | 140 | 141 |
142 |
143 |
144 | 145 |
146 |
147 | 148 | 156 | 157 | -------------------------------------------------------------------------------- /WebRoot/WUI/qrecord/js/swfobject.js: -------------------------------------------------------------------------------- 1 | /* SWFObject v2.2 2 | is released under the MIT License 3 | */ 4 | var swfobject=function(){var D="undefined",r="object",S="Shockwave Flash",W="ShockwaveFlash.ShockwaveFlash",q="application/x-shockwave-flash",R="SWFObjectExprInst",x="onreadystatechange",O=window,j=document,t=navigator,T=false,U=[h],o=[],N=[],I=[],l,Q,E,B,J=false,a=false,n,G,m=true,M=function(){var aa=typeof j.getElementById!=D&&typeof j.getElementsByTagName!=D&&typeof j.createElement!=D,ah=t.userAgent.toLowerCase(),Y=t.platform.toLowerCase(),ae=Y?/win/.test(Y):/win/.test(ah),ac=Y?/mac/.test(Y):/mac/.test(ah),af=/webkit/.test(ah)?parseFloat(ah.replace(/^.*webkit\/(\d+(\.\d+)?).*$/,"$1")):false,X=!+"\v1",ag=[0,0,0],ab=null;if(typeof t.plugins!=D&&typeof t.plugins[S]==r){ab=t.plugins[S].description;if(ab&&!(typeof t.mimeTypes!=D&&t.mimeTypes[q]&&!t.mimeTypes[q].enabledPlugin)){T=true;X=false;ab=ab.replace(/^.*\s+(\S+\s+\S+$)/,"$1");ag[0]=parseInt(ab.replace(/^(.*)\..*$/,"$1"),10);ag[1]=parseInt(ab.replace(/^.*\.(.*)\s.*$/,"$1"),10);ag[2]=/[a-zA-Z]/.test(ab)?parseInt(ab.replace(/^.*[a-zA-Z]+(.*)$/,"$1"),10):0}}else{if(typeof O.ActiveXObject!=D){try{var ad=new ActiveXObject(W);if(ad){ab=ad.GetVariable("$version");if(ab){X=true;ab=ab.split(" ")[1].split(",");ag=[parseInt(ab[0],10),parseInt(ab[1],10),parseInt(ab[2],10)]}}}catch(Z){}}}return{w3:aa,pv:ag,wk:af,ie:X,win:ae,mac:ac}}(),k=function(){if(!M.w3){return}if((typeof j.readyState!=D&&j.readyState=="complete")||(typeof j.readyState==D&&(j.getElementsByTagName("body")[0]||j.body))){f()}if(!J){if(typeof j.addEventListener!=D){j.addEventListener("DOMContentLoaded",f,false)}if(M.ie&&M.win){j.attachEvent(x,function(){if(j.readyState=="complete"){j.detachEvent(x,arguments.callee);f()}});if(O==top){(function(){if(J){return}try{j.documentElement.doScroll("left")}catch(X){setTimeout(arguments.callee,0);return}f()})()}}if(M.wk){(function(){if(J){return}if(!/loaded|complete/.test(j.readyState)){setTimeout(arguments.callee,0);return}f()})()}s(f)}}();function f(){if(J){return}try{var Z=j.getElementsByTagName("body")[0].appendChild(C("span"));Z.parentNode.removeChild(Z)}catch(aa){return}J=true;var X=U.length;for(var Y=0;Y0){for(var af=0;af0){var ae=c(Y);if(ae){if(F(o[af].swfVersion)&&!(M.wk&&M.wk<312)){w(Y,true);if(ab){aa.success=true;aa.ref=z(Y);ab(aa)}}else{if(o[af].expressInstall&&A()){var ai={};ai.data=o[af].expressInstall;ai.width=ae.getAttribute("width")||"0";ai.height=ae.getAttribute("height")||"0";if(ae.getAttribute("class")){ai.styleclass=ae.getAttribute("class")}if(ae.getAttribute("align")){ai.align=ae.getAttribute("align")}var ah={};var X=ae.getElementsByTagName("param");var ac=X.length;for(var ad=0;ad'}}aa.outerHTML='"+af+"";N[N.length]=ai.id;X=c(ai.id)}else{var Z=C(r);Z.setAttribute("type",q);for(var ac in ai){if(ai[ac]!=Object.prototype[ac]){if(ac.toLowerCase()=="styleclass"){Z.setAttribute("class",ai[ac])}else{if(ac.toLowerCase()!="classid"){Z.setAttribute(ac,ai[ac])}}}}for(var ab in ag){if(ag[ab]!=Object.prototype[ab]&&ab.toLowerCase()!="movie"){e(Z,ab,ag[ab])}}aa.parentNode.replaceChild(Z,aa);X=Z}}return X}function e(Z,X,Y){var aa=C("param");aa.setAttribute("name",X);aa.setAttribute("value",Y);Z.appendChild(aa)}function y(Y){var X=c(Y);if(X&&X.nodeName=="OBJECT"){if(M.ie&&M.win){X.style.display="none";(function(){if(X.readyState==4){b(Y)}else{setTimeout(arguments.callee,10)}})()}else{X.parentNode.removeChild(X)}}}function b(Z){var Y=c(Z);if(Y){for(var X in Y){if(typeof Y[X]=="function"){Y[X]=null}}Y.parentNode.removeChild(Y)}}function c(Z){var X=null;try{X=j.getElementById(Z)}catch(Y){}return X}function C(X){return j.createElement(X)}function i(Z,X,Y){Z.attachEvent(X,Y);I[I.length]=[Z,X,Y]}function F(Z){var Y=M.pv,X=Z.split(".");X[0]=parseInt(X[0],10);X[1]=parseInt(X[1],10)||0;X[2]=parseInt(X[2],10)||0;return(Y[0]>X[0]||(Y[0]==X[0]&&Y[1]>X[1])||(Y[0]==X[0]&&Y[1]==X[1]&&Y[2]>=X[2]))?true:false}function v(ac,Y,ad,ab){if(M.ie&&M.mac){return}var aa=j.getElementsByTagName("head")[0];if(!aa){return}var X=(ad&&typeof ad=="string")?ad:"screen";if(ab){n=null;G=null}if(!n||G!=X){var Z=C("style");Z.setAttribute("type","text/css");Z.setAttribute("media",X);n=aa.appendChild(Z);if(M.ie&&M.win&&typeof j.styleSheets!=D&&j.styleSheets.length>0){n=j.styleSheets[j.styleSheets.length-1]}G=X}if(M.ie&&M.win){if(n&&typeof n.addRule==r){n.addRule(ac,Y)}}else{if(n&&typeof j.createTextNode!=D){n.appendChild(j.createTextNode(ac+" {"+Y+"}"))}}}function w(Z,X){if(!m){return}var Y=X?"visible":"hidden";if(J&&c(Z)){c(Z).style.visibility=Y}else{v("#"+Z,"visibility:"+Y)}}function L(Y){var Z=/[\\\"<>\.;]/;var X=Z.exec(Y)!=null;return X&&typeof encodeURIComponent!=D?encodeURIComponent(Y):Y}var d=function(){if(M.ie&&M.win){window.attachEvent("onunload",function(){var ac=I.length;for(var ab=0;ab