uniapp上传音频文件到服务器

视频教程地址:

【uniapp录音上传组件,将录音上传到django服务器】 https://www.bilibili.com/video/BV1wi4y1p7FL/?share_source=copy_web&vd_source=e66c0e33402a09ca7ae1f0ed3d5ecf7c

  • uniapp 录制音频文件上传到django服务器保存到服务器 ,要求uniapp显示录制进度波形图 请提供完整代码
  • 以下是一个示例代码,演示了如何在uniapp中录制音频文件并将其上传到Django服务器,并在uniapp中显示录制进度波形图。

    在uniapp的页面中,你可以使用uni-voice组件来录制音频,并使用uni-upload组件来上传文件。在Django服务器端,你可以使用Django的文件上传功能来保存音频文件。

    uniapp页面代码(index.vue):

     
<template>
  <view class="container">
    <view class="waveform" :style="{ width: waveformWidth + 'px' }"></view>
    <view class="controls">
      <button @tap="startRecording" :disabled="isRecording">开始录制</button>
      <button @tap="stopRecording" :disabled="!isRecording">停止录制</button>
      <button @tap="uploadFile" :disabled="!recordedFile">上传文件</button>
    </view>
  </view>
</template>

<script>
export default {
  data() {
    return {
      isRecording: false,
      recordedFile: null,
      waveformWidth: 0,
      audioContext: null,
      audioRecorder: null,
      audioChunks: [],
    };
  },
  mounted() {
    this.audioContext = new (window.AudioContext || window.webkitAudioContext)();
  },
  methods: {
    startRecording() {
      this.isRecording = true;
      this.audioChunks = [];
      navigator.mediaDevices.getUserMedia({ audio: true })
        .then((stream) => {
          this.audioRecorder = new MediaRecorder(stream);
          this.audioRecorder.addEventListener('dataavailable', (event) => {
            this.audioChunks.push(event.data);
            this.drawWaveform();
          });
          this.audioRecorder.start();
        })
        .catch((error) => {
          console.error('Error accessing microphone:', error);
        });
    },
    stopRecording() {
      this.isRecording = false;
      this.audioRecorder.stop();
      this.audioRecorder.stream.getTracks().forEach((track) => track.stop());
      this.audioRecorder = null;
      this.recordedFile = new File(this.audioChunks, 'recorded_audio.wav', { type: 'audio/wav' });
    },
    drawWaveform() {
      const waveformElement = this.$refs.waveform;
      const canvas = waveformElement.getContext('2d');
      const width = waveformElement.width;
      const height = waveformElement.height;
      const data = new Uint8Array(this.audioChunks.reduce((acc, chunk) => acc + chunk.byteLength, 0));
      let offset = 0;
      this.audioChunks.forEach((chunk) => {
        const reader = new FileReader();
        reader.onload = () => {
          const array = new Uint8Array(reader.result);
          data.set(array, offset);
          offset += array.length;
          canvas.clearRect(0, 0, width, height);
          canvas.fillStyle = '#000000';
          for (let i = 0; i < width; i++) {
            const value = data[Math.floor(i * (data.length / width))];
            const barHeight = (value / 255) * height;
            canvas.fillRect(i, height - barHeight, 1, barHeight);
          }
        };
        reader.readAsArrayBuffer(chunk);
      });
    },
    uploadFile() {
      const formData = new FormData();
      formData.append('audio', this.recordedFile);
      uni.uploadFile({
        url: 'http://your-django-server/upload/',
        filePath: this.recordedFile.path,
        name: 'audio',
        formData: formData,
        success: (res) => {
          console.log('File uploaded:', res);
        },
        fail: (error) => {
          console.error('Error uploading file:', error);
        },
      });
    },
  },
};
</script>

<style>
.container {
  display: flex;
  flex-direction: column;
  align-items: center;
  justify-content: center;
  height: 100vh;
}

.waveform {
  width: 300px;
  height: 100px;
  background-color: #f0f0f0;
}

.controls {
  display: flex;
  justify-content: center;
  margin-top: 20px;
}

button {
  margin: 0 10px;
}
</style>

在Django服务器端,你需要设置一个视图函数来处理文件上传请求,并将音频文件保存到服务器上的某个目录中。以下是一个简单的示例代码:

 
  • from django.http import JsonResponse
    
    def upload_file(request):
        if request.method == 'POST' and request.FILES.get('audio'):
            audio_file = request.FILES['audio']
            with open('path/to/save/audio.wav', 'wb') as f:
                for chunk in audio_file.chunks():
                    f.write(chunk)
            return JsonResponse({'success': True})
        return JsonResponse({'success': False, 'message': 'Invalid request'})
    

    请将上述代码保存为一个Django视图函数,并将其添加到你的Django项目的URL配置中。

    注意:上述代码仅为示例,你可能需要根据你的具体需求进行适当的修改和调整。

  • 要保存文mp3文件
  • 如果你想保存音频文件为MP3格式,你可以使用lamejs库来将录制的音频文件转换为MP3格式。以下是修改后的示例代码:

    uniapp页面代码(index.vue):

     
<template>
  <view class="container">
    <view class="waveform" :style="{ width: waveformWidth + 'px' }"></view>
    <view class="controls">
      <button @tap="startRecording" :disabled="isRecording">开始录制</button>
      <button @tap="stopRecording" :disabled="!isRecording">停止录制</button>
      <button @tap="convertToMp3" :disabled="!recordedFile">转换为MP3</button>
      <button @tap="uploadFile" :disabled="!mp3File">上传文件</button>
    </view>
  </view>
</template>

<script>
import lamejs from 'lamejs';

export default {
  data() {
    return {
      isRecording: false,
      recordedFile: null,
      mp3File: null,
      waveformWidth: 0,
      audioContext: null,
      audioRecorder: null,
      audioChunks: [],
    };
  },
  mounted() {
    this.audioContext = new (window.AudioContext || window.webkitAudioContext)();
  },
  methods: {
    startRecording() {
      this.isRecording = true;
      this.audioChunks = [];
      navigator.mediaDevices.getUserMedia({ audio: true })
        .then((stream) => {
          this.audioRecorder = new MediaRecorder(stream);
          this.audioRecorder.addEventListener('dataavailable', (event) => {
            this.audioChunks.push(event.data);
            this.drawWaveform();
          });
          this.audioRecorder.start();
        })
        .catch((error) => {
          console.error('Error accessing microphone:', error);
        });
    },
    stopRecording() {
      this.isRecording = false;
      this.audioRecorder.stop();
      this.audioRecorder.stream.getTracks().forEach((track) => track.stop());
      this.audioRecorder = null;
      this.recordedFile = new File(this.audioChunks, 'recorded_audio.wav', { type: 'audio/wav' });
    },
    drawWaveform() {
      const waveformElement = this.$refs.waveform;
      const canvas = waveformElement.getContext('2d');
      const width = waveformElement.width;
      const height = waveformElement.height;
      const data = new Uint8Array(this.audioChunks.reduce((acc, chunk) => acc + chunk.byteLength, 0));
      let offset = 0;
      this.audioChunks.forEach((chunk) => {
        const reader = new FileReader();
        reader.onload = () => {
          const array = new Uint8Array(reader.result);
          data.set(array, offset);
          offset += array.length;
          canvas.clearRect(0, 0, width, height);
          canvas.fillStyle = '#000000';
          for (let i = 0; i < width; i++) {
            const value = data[Math.floor(i * (data.length / width))];
            const barHeight = (value / 255) * height;
            canvas.fillRect(i, height - barHeight, 1, barHeight);
          }
        };
        reader.readAsArrayBuffer(chunk);
      });
    },
    convertToMp3() {
      const wavData = new Uint8Array(this.audioChunks.reduce((acc, chunk) => acc + chunk.byteLength, 0));
      let offset = 0;
      this.audioChunks.forEach((chunk) => {
        const array = new Uint8Array(chunk);
        wavData.set(array, offset);
        offset += array.length;
      });
      const wavFile = new Blob([wavData], { type: 'audio/wav' });
      const mp3Encoder = new lamejs.Mp3Encoder(1, this.audioContext.sampleRate, 128);
      const samples = new Int16Array(wavData.buffer);
      const mp3Data = [];
      let remaining = samples.length;
      let index = 0;
      while (remaining >= 0) {
        const bufferSize = Math.min(remaining, 1152);
        const buffer = samples.subarray(index, index + bufferSize);
        const mp3Buffer = mp3Encoder.encodeBuffer(buffer);
        mp3Data.push(mp3Buffer);
        remaining -= bufferSize;
        index += bufferSize;
      }
      const mp3Buffer = mp3Encoder.flush();
      mp3Data.push(mp3Buffer);
      const mp3DataBlob = new Blob(mp3Data, { type: 'audio/mp3' });
      this.mp3File = new File([mp3DataBlob], 'recorded_audio.mp3', { type: 'audio/mp3' });
    },
    uploadFile() {
      const formData = new FormData();
      formData.append('audio', this.mp3File);
      uni.uploadFile({
        url: 'http://your-django-server/upload/',
        filePath: this.mp3File.path,
        name: 'audio',
        formData: formData,
        success: (res) => {
          console.log('File uploaded:', res);
        },
        fail: (error) => {
          console.error('Error uploading file:', error);
        },
      });
    },
  },
};
</script>

<style>
.container {
  display: flex;
  flex-direction: column;
  align-items: center;
  justify-content: center;
  height: 100vh;
}

.waveform {
  width: 300px;
  height: 100px;
  background-color: #f0f0f0;
}

.controls {
  display: flex;
  justify-content: center;
  margin-top: 20px;
}

button {
  margin: 0 10px;
}
</style>

请确保在uniapp项目中安装了lamejs库,可以使用以下命令进行安装:

 
npm install lamejs

在Django服务器端,你需要修改视图函数来处理MP3文件的上传和保存。以下是一个简单的示例代码:

 
  • from django.http import JsonResponse
    
    def upload_file(request):
        if request.method == 'POST' and request.FILES.get('audio'):
            audio_file = request.FILES['audio']
            with open('path/to/save/audio.mp3', 'wb') as f:
                for chunk in audio_file.chunks():
                    f.write(chunk)
            return JsonResponse({'success': True})
        return JsonResponse({'success': False, 'message': 'Invalid request'})
    

    请将上述代码保存为一个Django视图函数,并将其添加到你的Django项目的URL配置中。

    注意:上述代码仅为示例,你可能需要根据你的具体需求进行适当的修改和调整。

  • npm install lamejs 下载不下来
  • 如果你无法通过npm install lamejs命令下载lamejs库,可能是由于网络问题或库的可用性问题。你可以尝试以下解决方案:

    1. 使用淘宝镜像:在命令行中执行以下命令,将npm的镜像源切换为淘宝镜像,然后再次尝试安装:

       
  • npm config set registry https://registry.npm.taobao.org
    
  • 使用cnpm:cnpm是淘宝镜像提供的npm镜像的命令行工具,可以尝试使用cnpm来安装:

     
    1. npm install -g cnpm --registry=https://registry.npm.taobao.org
      cnpm install lamejs
      
    2. 手动下载:如果以上方法仍然无法下载,你可以尝试手动下载lamejs库的压缩包。你可以在https://www.npmjs.com/package/lamejs上找到lamejs的页面,然后下载最新版本的压缩包。下载完成后,解压缩并将其中的文件复制到你的uniapp项目中的合适位置。

    请注意,以上解决方案仅供参考,具体的操作可能因个人环境和网络条件而有所不同。如果问题仍然存在,请尝试在其他网络环境下进行安装,或者考虑使用其他类似的库来处理音频文件的转换。

  • npm ERR! code CERT_HAS_EXPIRED
    npm ERR! errno CERT_HAS_EXPIRED
    npm ERR! request to https://registry.npm.taobao.org/cnpm failed, reason: certificate has expired
    
    npm ERR! A complete log of this run can be found in:
    npm ERR!     C:\Users\Administrator\AppData\Local\npm-cache\_logs\2024-01-25T09_21_52_636Z-debug-0.log
  • 这个错误提示表明你的npm证书已过期,导致无法从https://registry.npm.taobao.org下载lamejs库。你可以尝试以下解决方案:

    1. 更新npm:运行以下命令来更新npm到最新版本:

       
  • npm install -g npm
    
  • 清除npm缓存:运行以下命令来清除npm缓存:

     
  • npm cache clean --force
    
  • 使用其他镜像源:尝试使用其他npm镜像源来安装lamejs。你可以尝试使用npm的官方镜像源或其他可靠的镜像源。运行以下命令来切换镜像源:

     
  • npm config set registry https://registry.npmjs.org/
    
  • 使用代理:如果你在使用代理服务器,请确保npm配置了正确的代理设置。你可以通过运行以下命令来配置代理:

     
    1. npm config set proxy http://your-proxy-server:port
      npm config set https-proxy http://your-proxy-server:port
      

    如果以上解决方案仍然无法解决问题,可能是由于网络或其他环境问题导致的。你可以尝试在其他网络环境下进行安装,或者考虑使用其他类似的库来处理音频文件的转换。

这里笔者使用手动下载的方式

要手动下载lamejs到UniApp项目中,可以按照以下步骤进行操作:

  1. 打开lamejs的GitHub页面:https://github.com/zhuker/lamejs

  2. 在页面上找到并点击绿色的 “Code” 按钮,然后选择 “Download ZIP” 下载lamejs的源代码压缩包。

  3. 解压下载的ZIP文件,得到一个名为 “lamejs-master” 的文件夹。

  4. 打开你的UniApp项目,在项目的根目录下找到 “static” 文件夹(如果没有则手动创建一个)。

  5. 将解压得到的 “lamejs-master” 文件夹复制到 “static” 文件夹中。

  6. 在你的UniApp项目中,找到需要使用lamejs的页面或组件。

  7. 在需要使用lamejs的页面或组件中,使用相对路径引入lamejs的相关文件。例如,如果你在页面的script标签中引入lamejs,可以使用以下代码:

 
  • import lamejs from '@/static/lamejs-master/lame.min.js';
    
    1. 现在你可以在页面或组件中使用lamejs的功能了。

    请注意,以上步骤假设你已经安装了UniApp开发环境,并且已经创建了一个UniApp项目。如果你的项目结构有所不同,你需要根据实际情况进行相应的调整。

lamejs (v1.2.1) - Pure JavaScript MP3 Encoder | BootCDN - Bootstrap 中文网开源项目免费 CDN 加速服务

 

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:/a/349019.html

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

svn和git的本质区别是什么

参考&#xff1a; https://blog.csdn.net/feiying0canglang/article/details/126550676 上边图中&#xff0c;跨越了区的箭头&#xff0c;它中间的区数据都会同步。例如&#xff1a;git checkout &#xff0c;它是将本地仓库数据更新到暂存区和工作区的。\ 理解 gitlab和svn都…

【深度优先搜索】【C++算法】834 树中距离之和

作者推荐 【动态规划】【map】【C算法】1289. 下降路径最小和 II 本文涉及知识点 深度优先搜索 树 图论 LeetCode834 树中距离之和 给定一个无向、连通的树。树中有 n 个标记为 0…n-1 的节点以及 n-1 条边 。 给定整数 n 和数组 edges &#xff0c; edges[i] [ai, bi]表…

【AIGC】Diffusers:训练扩散模型

前言 无条件图像生成是扩散模型的一种流行应用&#xff0c;它生成的图像看起来像用于训练的数据集中的图像。通常&#xff0c;通过在特定数据集上微调预训练模型来获得最佳结果。你可以在HUB找到很多这样的模型&#xff0c;但如果你找不到你喜欢的模型&#xff0c;你可以随时训…

vue常用指令(v-for)

一、v-for 指令 作用: 根据数据生成列表结构 二、代码演示 1、在li标签中获取数组元素 代码 <!DOCTYPE html> <html lang"en"><head><meta charset"UTF-8" /><meta name"viewport" content"widthdevice-wid…

2024年 复习 HTML5+CSS3+移动web 笔记 之CSS遍

第一天第二天第三天 1.1 引入方式 1.2 选择器 1.3 画盒子 1.4 文字控制 1.5 综合案例 一 新闻详情 2.1 复合选择器 2.2 伪类选择器 2.3 CSS 特性 2.4 Emmet 写法 2.5 背景属性 2.6 显示模式 2.6 综合案例 一 热词 &#xff08;设计稿&#xff1f;&#xff09; 2.7 综合案例 一…

金蝶云星空-表单插件,点击事件(一)

表单插件&#xff0c;点击事件 BarItemClick、AfterBarItemClick 有时候我们在不通的场景中使用到自己的企业的逻辑思维 业务场景&#xff1a;采购订单上&#xff0c;增加一个按钮tbCeShi&#xff0c;添加下面的插件&#xff0c;弹出一个对话框&#xff1b; 添加一个按钮&am…

前端怎么监听手机键盘是否弹起

摘要&#xff1a; 开发移动端中&#xff0c;经常会遇到一些交互需要通过判断手机键盘是否被唤起来做的&#xff0c;说到判断手机键盘弹起和收起&#xff0c;应该都知道&#xff0c;安卓和ios判断手机键盘是否弹起的写法是有所不同的&#xff0c;下面讨论总结一下两端的区别以及…

前端学习生产环境、开发环境、测试环境

1、路径 定义是什么环境 NODE_ENVdevelopment 开发环境 2、.env 端口号 3、.env.development 开发环境 4、.env.production 生产环境 5、.env.test 测试环境 6、如何访问&#xff0c;通过process.env进行访问 学习中.......

SqlAlchemy使用教程(六) -- ORM 表间关系的定义与CRUD操作

SqlAlchemy使用教程(一) 原理与环境搭建SqlAlchemy使用教程(二) 入门示例及编程步骤SqlAlchemy使用教程(三) CoreAPI访问与操作数据库详解SqlAlchemy使用教程(四) MetaData 与 SQL Express Language 的使用SqlAlchemy使用教程(五) ORM API 编程入门 本章内容&#xff0c;稍微有…

SpringMVC-对静态资源的访问

1.工程中加入静态资源 在webapp下创建static文件夹&#xff0c;此文件夹专门放入静态资源 2.使项目可以处理静态资源的请求 在SpringMVC配置文件中添加以下语句 1.引入命名空间 xmlns:mvc"http://www.springframework.org/schema/mvc" xsi:schemaLocation“http…

Laravel 10.x 里如何使用ffmpeg

原理上很简单&#xff0c;就是使用命令行去调用ffmpeg&#xff0c;然后分析一下输出是不是有错误。 安装 首先安装 symfony/process&#xff0c;主要用于包装一下&#xff0c;用来代替 exec, passthru, shell_exec and system 。 composer require symfony/process composer…

75 C++对象模型探索。C++关于 虚函数表指针位置分析

如果一个类中&#xff0c;有虚函数&#xff0c;针对这个类会产生一个虚函数表。 生成这个类对象的时候&#xff0c;会有一个虚函数表指针&#xff0c;这个指针会指向这个虚函数表的开始地址。 我们本节就研究这个vptr指针。注意&#xff0c;vptr指针在 类对象中的位置。 证明…

【算法】糖果(差分约束)

题目 幼儿园里有 N 个小朋友&#xff0c;老师现在想要给这些小朋友们分配糖果&#xff0c;要求每个小朋友都要分到糖果。 但是小朋友们也有嫉妒心&#xff0c;总是会提出一些要求&#xff0c;比如小明不希望小红分到的糖果比他的多&#xff0c;于是在分配糖果的时候&#xff…

echarts 绘制垂直滚动热力图

问题1&#xff1a;提示功能无效 问题2&#xff1a;值筛选无效 效果 在线浏览 下载echarts官网例子(heatmap Examples - Apache ECharts) 稍作改动&#xff1a; generateData 入参改为长度和宽度noise.perlin2(i / 40, j / 20) Math.random() * 5y轴倒置指定zlevel为2 通过定…

链表--226. 翻转二叉树/medium 理解度A

226. 翻转二叉树 1、题目2、题目分析3、复杂度最优解代码示例4、适用场景 1、题目 给你一棵二叉树的根节点 root &#xff0c;翻转这棵二叉树&#xff0c;并返回其根节点。 示例 1&#xff1a; 输入&#xff1a;root [4,2,7,1,3,6,9] 输出&#xff1a;[4,7,2,9,6,3,1]示例 2&…

python:socket基础操作(3)-《udp接收消息》

收跟发基本核心思想差不多&#xff0c;只不过收信息需要去绑定一下端口&#xff0c;如果我们发信息没有绑定端口&#xff0c;那系统会随机分配一个&#xff0c;如果是收信息&#xff0c;那我们必须要求自己绑定端口才行 基础的接收数据 import socketudp_socket socket.socke…

华清远见作业第三十三天——C++(第二天)

思维导图&#xff1a; 题目&#xff1a; 自己封装一个矩形类(Rect)&#xff0c;拥有私有属性:宽度(width)、高度(height)&#xff0c; 定义公有成员函数&#xff1a; 初始化函数&#xff1a;void init(int w, int h) 更改宽度的函数&#xff1a;set_w(int w) 更改高度的函数…

如何使用 WebRTC 与 Kurento 建立视频会议 App

本文作者 WebRTC Ventures 工程师。在 RTC 2018 实时互联网大会上&#xff0c;WebRTC Ventures 的资深软件工程师&#xff0c;将围绕 WebRTC 开发带来经验分享。欢迎访问RTC 开发者社区&#xff0c;与更多WebRTC开发者交流经验。 了解 WebRTC 如何工作的一种简单方式是通过学习…

安全防御综合组网实验

题目 要求 生产区在工作时间可以访问服务器区&#xff0c;仅可以访问http服务器。办公区全天可以访问服务器区&#xff0c;其中10.0.2.20 可以访问FTP服务器和http服务器。10.0.2.10仅可以ping通10.0.3.10。办公区在访问服务器区时采用匿名认证的方式进行上网行为管理。办公区…

20.云原生之GitLab集成Runner

云原生专栏大纲 文章目录 GitLab RunnerGitLab Runner 介绍GitLab Runner分类GitLab Runner工作流程 Gitlab集成Gitlab RunnerGitLab Runner 版本选择Runner在CitLab中位置专用Runner在gitlab中位置群组Runner在gitlab中位置共享Runner在gitlab中位置 GitLab部署Gitlab Runner…