基于Qt编写的在线音乐播放器

Posted guishangppy

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了基于Qt编写的在线音乐播放器相关的知识,希望对你有一定的参考价值。

思路: Qt中提供了音视频播放的类,类中提供了很多播放类的接口供我们调用,基本可以实现一个完整播放器的所有功能,由于想要实现的是支持在线搜索和播放的,所以要先解决音频的来源,再进行ui界面的设计,最后将背后的功能实现。

 一,调用网易云API

如果想自己写服务器作为音乐播放的来源的话比较难实现,所以就调用网易云音乐的API,用特定的请求数据格式获得数据后进行解析后就可以得到音乐的 Url  格式,再通过Qt提供的在线播放类播放即可。 

网易云音乐提供了这样一个 API 用于公共请求使用:   https://music.cyrilstudio.top

成功进入后我们点击查看文档 

 点击开始使用:

 点击使用指南可以查看该API提供了哪些基本功能,并提供了不同的功能调用的方法

 以搜索歌曲为例,请求资源的格式为 :https://music.cyrilstudio.top/search?keywords=歌曲名称

 我们先以他提供的例子将 Url 进行验证,如果得到如下的格式说明正确

 这是对方服务器接收你的请求后返回的 json 格式的文本,使用 http://json.cn   进行翻译,查看是否包含所需要的信息,我们将 json 格式的文本全部复制到这个网页中进行解析,得到如下信息

 id 是音乐ID ,可以唯一标识一首音乐,其他的还有歌曲名,歌手名,歌曲时长等信息都在里面,需要将其解析出来。

二,使用Qt中的 QNetworkAccessManager 类发送和接收数据

 QNetworkAccessManager 也被称为网络大管家类,是因为所有和网络相关的接口都是围绕QNetworkAccessManager创造出来的对象,并且一个应用程序只要有一个QNetworkAccessManager对象即可该类控制着应用程序发送请求和接受回复。该类也承载着一切公共的配置以及所发请求的设置,还包含了代理配置、缓存配置、以及相对应的各种信号,reply(应答)信号可以用来监视网络活动。所以我们可以通过这一个对象完成信息的收发。具体实现如下:

  QNetworkAccessManager* http_acc = new QNetworkAccessManager;   //定义并实例化一个网络管家   
   QString str;
    str=QString("https://music.cyrilstudio.top/search?keywords=海阔天空");  //将请求格式作为字符串保存
    QNetworkRequest request;          //定义一个请求对象
    request.setUrl(QString(str));      //将请求格式设置给请求对象
    http_acc->get(request);              //请求   

这样对方的服务器就会接收到正确的请求,之后便会将你所请求的内容以 json 格式发送过来,先通过接收函数接收对方发送的 json 文本后再进行解析。

当然Qt 也提供了接收信息的类   QNetworkReply  ,通过定义一个接收对象,将内容全部读取出来

QNetworkReply* r;                          //定义一个接收信息对象
QByteArray searchInfo= r->readAll();        //全部读取

 三,解析json文本

 1,先将收到的信息提取后转换为 json 文件对象,并检查内容是否符合 json 语法。

        searchInfo = r->readAll();          // 读取全部信息
        QJsonParseError err;               //错误信息对象
        QJsonDocument json_recv = QJsonDocument::fromJson(searchInfo,&err);//将json文本转换为 json 文件对象
        if(err.error != QJsonParseError::NoError)             //判断是否符合语法
        
            qDebug() <<"搜索歌曲Json获取格式错误"<< err.errorString();
            return;
        

2,如果语法合法后,我们就要检查是否有我们想要的信息,并对各个信息的 key 值作为解析条件提取出来。 

        QJsonObject totalObject = json_recv.object();              
        QStringList keys = totalObject.keys();    // 列出json里所有的key
        if(keys.contains("result"))                 //如果有结果
               //在 json 文本中 花括号里面是QJsonObject对象, []方括号里面是QJsonArray

            QJsonObject resultObject = totalObject["result"].toObject();     //就将带 result 的内容提取后转换为对象
            QStringList resultKeys = resultObject.keys();      //保存所有key
            if(resultKeys.contains("songs"))                    //如果 key 为songs ,代表找到了歌曲
            
                QJsonArray array = resultObject["songs"].toArray();
                for(auto i : array)                   //开始获取歌曲中的信息
                
                    QJsonObject object = i.toObject();
                    musicId = object["id"].toInt();                         // 音乐id
                    musicDuration = object["duration"].toInt();             // 音乐长度
                    musicName = object["name"].toString();                  // 音乐名
                    mvId = object["mvid"].toInt();                          // mvid
                    QStringList artistsKeys = object.keys();
                    if(artistsKeys.contains("artists"))                //如果result中包含了 artists
                    
                        QJsonArray artistsArray = object["artists"].toArray();   //将 artist 的内容提取后保存
                        for(auto j : artistsArray)              
                        
                            QJsonObject object2 = j.toObject();
                            singerName = object2["name"].toString();         // 歌手名
                        
                    
                    if(artistsKeys.contains("album"))                //包含了专辑
                    
                        QJsonObject albumObjct = object["album"].toObject();
                        albumName = albumObjct["name"].toString();            // 专辑名
                    
//                     qDebug()<<"音乐ID:"+QString::number(musicId);
//                     qDebug()<<"音乐名:"+musicName;
//                     qDebug()<<"歌手名:"+singerName;
//                     qDebug()<<"总时长:"+QString::number(musicDuration);
//                    qDebug()<<"专辑名:"+albumName;
//                    qDebug()<<"mv的id:"+QString::number(mvId);

                    
        emit searchFinal(number,musicId,mvId,musicName,singerName,albumName,musicDuration);     //发射信号
                     number+=1;         

                
            

            number = 0;
        

四,播放 url 歌曲 

 我们进行打印调试一下是否真正得到了想要的信息,以 《鼓楼》这首歌作为关键字进行搜索为例

 发现已经得到了我们想要的信息,所以接下来我们将获取的音乐ID 以一定的Url 格式进行搜索进行验证, http:// https://music.163.com/song/media/outer/url?id=音乐ID

有了这个Url 之后我们就可以播放音乐了,如下:

     QMediaPlayer *player=new QMediaPlayer;                 //播放对象
     QMediaPlayerlist playerlist=new QMediaPlayerlist;      //播放列表对象
     QString url;              //保存url
     url=QString("https://music.163.com/song/media/outer/url?id=%0").arg(musicId);  //将音乐ID作为格式输入到url中
     playlist->addMedia(QUrl(url));                     //添加一音乐到播放列表中
     player->setMedia(playlist);                        //将列表设置到播放器中
     player->play();                                  //播放

 这样就可以听到自己想要听的音乐了,这就完成了播放器的主干,其余的功能可以慢慢查看Qt中的帮助进行补充。

自己做好的简易播放器如下,中间的空白部分功能还未完全添加

 1,搜索(在线播放)

 2,本地播放,选择想播放的歌曲(可以选择很多),点击播放即可

注:源码在我的资源中 

Qt编写带频谱的音乐播放器

之前有个项目需要将音频文件的频谱显示出来,想了很多办法,后面发现fmod这个好东西,还是跨平台的,就一个头文件+一个库文件就行,简单小巧功能强大,人家做的真牛逼。为了不卡住界面,采用了多线程处理。

执行文件下载:https://pan.baidu.com/s/1JIjiCv800KPDZS9aSRPObQ 

 

技术分享图片技术分享图片

1:可获取整个声音文件采样值数据
2:可实时获取当前播放位置的采样值数据
3:可设置采样的步长和数量
4:可开始播放/暂停播放/停止播放
5:多线程处理,超流畅
6:可设置当前播放位置
7:可设置音量

#ifndef FMODTHREAD_H
#define FMODTHREAD_H

/**
 * fmod音乐播放类 作者:feiyangqingyun(QQ:517216493) 2017-9-12
 * 1:可获取整个声音文件采样值数据
 * 2:可实时获取当前播放位置的采样值数据
 * 3:可设置采样的步长和数量
 * 4:可开始播放/暂停播放/停止播放
 * 5:多线程处理,超流畅
 * 6:可设置当前播放位置
 * 7:可设置音量
 * 参考文章:http://blog.csdn.net/fengyhack/article/details/43318575
 */

#include <QThread>

class FMOD_SYSTEM;
class FMOD_SOUND;
class FMOD_CHANNEL;

class FmodThread : public QThread
{
    Q_OBJECT
public:
    explicit FmodThread(QObject *parent = 0);
    ~FmodThread();

protected:
    void run();

private:
    bool stopped;           //停止线程标志位
    bool isPlayWave;        //开始播放标志位
    bool isPauseWave;       //暂停播放标志位
    bool isStopWave;        //停止播放标志位
    bool isReadWave;        //读取当前位置采样值标志位

    int step;               //采样值步长
    int count;              //采样点总数
    int interval;           //采样间隔
    bool showWaveDataAll;   //是否显示总采样
    QString fileName;       //当前声音文件

    FMOD_SYSTEM *system;    //fmod结构体
    FMOD_SOUND *sound;      //播放声音对象
    FMOD_CHANNEL *channel;  //播放声音通道

private slots:
    //获取当前位置采样值数据
    void readWaveData();
    //获取所有采样值数据
    void readWaveDataAll();

    //开始播放
    void playWave();
    //暂停播放
    void pauseWave();
    //停止播放
    void stopWave();

signals:
    //开始播放信号
    void playStart();
    //停止播放信号
    void playStop();
    //暂停播放信号
    void playPause();

    //当前播放时长
    void filePositionReceive(uint position, bool isPlay);
    //总时长
    void fileLengthReceive(uint length);
    //音量大小
    void fileVolumeReceive(int volume, bool mute);

    //当前声音正在播放位置采样值数据
    void waveDataReceive(const QVector<float> &waveData);
    //当前声音所有采样值数据
    void waveDataAllReceive(const QVector<float> &waveData);

public slots:
    //设置采样值步长
    void setStep(int step);
    //设置采样点总数
    void setCount(int count);
    //设置采样间隔
    void setInterval(int interval);
    //设置是否显示总采样
    void setShowWaveDataAll(bool showWaveDataAll);
    //设置要播放的声音文件
    void setFileName(const QString &fileName);

    //播放
    void play();
    //暂停
    void pause();
    //停止
    void stop();
    //停止线程
    void stopAll();

    //设置播放进度位置
    void setPosition(int position);
    //设置音量
    void setVolume(int volume);
    //设置静音
    void setMute(bool mute);

};

#endif // FMODTHREAD_H

以上是关于基于Qt编写的在线音乐播放器的主要内容,如果未能解决你的问题,请参考以下文章

QT软件开发-基于FFMPEG设计视频播放器-支持软解与硬解

基于树莓派4B设计的音视频播放器(从0开始)

Qt Quick 多媒体 - 播放音乐和视频

QT软件开发-基于FFMPEG设计视频播放器-解码音频

QT软件开发-基于FFMPEG设计视频播放器-GPU硬解图像

QT软件开发-基于FFMPEG设计视频播放器-支持流媒体地址播放