http发送mp3及录音保存成mp3文件,http接收保存mp3文件实现过程。


一:http发送mp3代码:

import java.io.File;
import java.io.IOException;
import java.nio.charset.Charset;

import org.apache.http.HttpEntity;
import org.apache.http.client.methods.CloseableHttpResponse;
import org.apache.http.client.methods.HttpPost;
import org.apache.http.entity.mime.MultipartEntityBuilder;
import org.apache.http.entity.mime.content.FileBody;
import org.apache.http.impl.client.CloseableHttpClient;
import org.apache.http.impl.client.HttpClients;
import org.apache.http.util.EntityUtils;

public class HttpPostMp3Test
{
    public static void  upload(String localFile, String url_str)
    {
        CloseableHttpClient httpClient = null;
        CloseableHttpResponse response = null;
        try
        {
            httpClient = HttpClients.createDefault();

            // 把一个普通参数和文件上传给下面这个地址 是一个servlet
            HttpPost httpPost = new HttpPost(url_str);

            // 把文件转换成流对象FileBody
            FileBody bin = new FileBody(new File(localFile));


            HttpEntity reqEntity = MultipartEntityBuilder.create()
                    // 相当于<input type="file" name="file"/>
                    .addPart("file", bin).build();


            httpPost.setEntity(reqEntity);

            // 发起请求 并返回请求的响应
            response = httpClient.execute(httpPost);

            System.out.println("The response value of token:" + response.getFirstHeader("token"));

            // 获取响应对象
            HttpEntity resEntity = response.getEntity();
            if (resEntity != null)
            {
                // 打印响应长度
                System.out.println("Response content length: " + resEntity.getContentLength());
                // 打印响应内容
                System.out.println("Response content : " + EntityUtils.toString(resEntity, Charset.forName("UTF-8")));
            }

            // 销毁
            EntityUtils.consume(resEntity);
        } catch (Exception e)
        {
            e.printStackTrace();
        } finally
        {
            try
            {
                if (response != null)
                {
                    response.close();
                }
            } catch (IOException e)
            {
                e.printStackTrace();
            }

            try
            {
                if (httpClient != null)
                {
                    httpClient.close();
                }
            } catch (IOException e)
            {
                e.printStackTrace();
            }
        }
    }

    public static void main(String[] args)
    {
        HttpPostMp3Test.upload("D:\\video\\test3.mp3", "http://localhost:9030/api/mp3");
    }
}



二:录音保存成mp3文件代码:

import java.io.File;
import java.util.Scanner;

import javax.sound.sampled.AudioFileFormat;
import javax.sound.sampled.AudioFormat;
import javax.sound.sampled.AudioInputStream;
import javax.sound.sampled.AudioSystem;
import javax.sound.sampled.DataLine;
import javax.sound.sampled.TargetDataLine;

public class SoundRecordingTest {
    AudioFormat audioFormat;
    TargetDataLine targetDataLine;

    public static void main(String args[]) {
        new SoundRecordingTest();
    }

    public SoundRecordingTest() {
        System.out.println("y开始n结束");
        @SuppressWarnings("resource")
        Scanner input = new Scanner(System.in);
        String Sinput = input.next();
        long testtime = System.currentTimeMillis();
        if(Sinput.equals("y")){
            captureAudio();//调用录音方法
        }
        @SuppressWarnings("resource")
        Scanner input_2 = new Scanner(System.in);
        String Sinput_2 = input_2.next();
        if(Sinput_2.equals("n")){
            targetDataLine.stop();
            targetDataLine.close();
        }
        System.out.println("录音了"+(System.currentTimeMillis()-testtime)/1000+"秒!");
    }

    public void captureAudio() {
        try {
            audioFormat = getAudioFormat();// 构造具有线性 PCM 编码和给定参数的 AudioFormat。
            DataLine.Info dataLineInfo = new DataLine.Info(TargetDataLine.class, audioFormat);
            // 根据指定信息构造数据行的信息对象,这些信息包括单个音频格式。此构造方法通常由应用程序用于描述所需的行。
            // lineClass - 该信息对象所描述的数据行的类
            // format - 所需的格式
            targetDataLine = (TargetDataLine) AudioSystem.getLine(dataLineInfo);
            // 如果请求 DataLine,且 info 是 DataLine.Info 的实例(至少指定一种完全限定的音频格式),
            // 上一个数据行将用作返回的 DataLine 的默认格式。
            new CaptureThread().start();
            // 开启线程
        } catch (Exception e) {
            e.printStackTrace();
            System.exit(0);
        }
    }

    private AudioFormat getAudioFormat() {
        float sampleRate = 8000F;
        // 8000,11025,16000,22050,44100 采样率
        int sampleSizeInBits = 8;
        // 8,16 每个样本中的位数
        int channels = 2;
        // 1,2 信道数(单声道为 1,立体声为 2,等等)
        boolean signed = true;
        // true,false
        boolean bigEndian = false;
        // true,false 指示是以 big-endian 顺序还是以 little-endian 顺序存储音频数据。
        return new AudioFormat(sampleRate, sampleSizeInBits, channels, signed, bigEndian);// 构造具有线性 PCM 编码和给定参数的
                                                                                            // AudioFormat。
    }

    class CaptureThread extends Thread {
        public void run() {
            AudioFileFormat.Type fileType = null;
            // 指定的文件类型
            File audioFile = null;
            // 设置文件类型和文件扩展名
            // 根据选择的单选按钮。
            fileType = AudioFileFormat.Type.WAVE;
            audioFile = new File("test3.mp3");
            try {
                targetDataLine.open(audioFormat);
                // format - 所需音频格式
                targetDataLine.start();
                // 当开始音频捕获或回放时,生成 START 事件。
                AudioSystem.write(new AudioInputStream(targetDataLine), fileType, audioFile);
                // new AudioInputStream(TargetDataLine
                // line):构造从指示的目标数据行读取数据的音频输入流。该流的格式与目标数据行的格式相同,line - 此流从中获得数据的目标数据行。
                // stream - 包含要写入文件的音频数据的音频输入流
                // fileType - 要写入的音频文件的种类
                // out - 应将文件数据写入其中的外部文件

            } catch (Exception e) {
                e.printStackTrace();
            }
        }
    }
}



三:http接收保存mp3文件实现过程总的思路就是找出MP3内容的头和尾,截取头和尾之间的内容保存成.mp3文件就可以了。

MP3音乐文件分两种情况,一种是接收过来的是真正的MP3音乐文件,另一种是录音保存成MP3文件。

真正的MP3音乐文件分成有带标签头的MP3音乐文件和没有带标签头的MP3音乐文件。
有带标签头的MP3文件如下图所示:(0x49,0x44,0x33)代表ID3,

没有带标签头的MP3音乐文件:如下图所示


MP3音乐文件不管有没有带标签头,内容帧开始符一般都是0xFF开头。

MP3音乐文件结束一般以TAG(0x54,0x41,0x47)结束符128字节,这128字节包含TAG总共128字节,多出来的音乐文件信息可以不管不会影响到播放。

如下两图所示

上图所示明显大于128字节,只要截取128字节就可以了,不会影响到播放。

上图所示刚好128字节。


录音保存成MP3文件没有以上规律,但是录音的MP3一般是不会包含(0x0D,0x0A)回车换行
经过对几个录音MP3文件的分析发现经过http发送过来的录音MP3就一个规律就是以双(0x0D,0x0A,0x0D,0x0A)回车换行开头,以单(0x0D,0x0A)回车换行结束。




参考:
https://www.cnblogs.com/zfy0098/p/5230465.html
https://blog.csdn.net/haoranhaoshi/article/details/87888382


https://blog.csdn.net/ffjffjffjffjffj/article/details/99691239
https://blog.csdn.net/xwjazjx1314/article/details/56288997
https://blog.csdn.net/IOT_SHUN/article/details/79952466

猜你喜欢

转载自www.cnblogs.com/yebinghuai/p/12044395.html