实现的功能

1.可以播放本地音乐
2.实现常用功能(上下曲,播放/暂停,显示播放时长)
3.通过网易云API搜索歌曲

实现步骤

1.在pro文件里面添加multimedia库和network库
2.设计好自己的UI界面
3.添加自己需要的头文件并定义自己需要的变量
4.打开自己存放歌曲的目录,将歌曲添加到歌曲列表然后进行播放
5.通过信号与槽机制实现常用的功能
6.接入网易云API进行歌曲搜索

ui界面展示


代码模块展示

添加本地文件

file = QFileDialog::getOpenFileName(this,"Open File","D:/Music","mp3 Files (*.mp3)");//打开MP3文件,如果需要添加其余音频文件,只需继续添加过滤项即可playlist->addMedia(QUrl(file));//将自己需要的MP3文件添加入播放列表//以下是去掉前面的路径并且追加显示到plainTextEdit(将名字复制到另一个字符串)int fi=0,af=9;//fi为新字符串的开始位置,af为歌曲名字的第一个位置(自己的路径)QString s;//新字符串while(file[af]!='\0')将歌曲名字移动到数组开头{s[fi]=file[af];fi++;af++;}s[fi]='\0';//添加字符串结束标志ui->plainTextEdit->appendPlainText(s);//显示到plainTextEdit

播放/暂停

//通过标志位来实现播放与暂停
if(x==0)   //如果是停止状态或暂停就播放
{player->play();x=1;    //置1下一次点击就会暂停
}
else if(x==1)         //如果是播放状态就暂停
{player->pause();    x=0;    //置0下一次点击就会播放
}

下一曲

  //点击下一曲,如果当前歌曲是最后一首歌曲,就跳到第一首歌,其余则直接跳到下一首int m_Value=playlist->currentIndex();    //当前歌曲是第几个int m_Amount=playlist->mediaCount();    //总歌曲数量if(m_Value<m_Amount)    //判断当前歌曲是否为最后一首{m_Value=m_Value+1;    //播放的位置+1playlist->setCurrentIndex(m_Value);   //重新设置播放的位置player->play();    }else{m_Value=0;playlist->setCurrentIndex(m_Value);    //跳到第一首player->play();}

上一曲与之类似

时间显示

//通过槽函数实现
void Widget::timechange(qint64 duration)
{int secs = duration/1000; //全部秒数int mins = secs/60;//分secs = secs % 60;//秒QString str=QString::asprintf("%d:%d",mins,secs);//转换为字符串ui->lcdNumber->display(str);//用lcdNumber进行显示
}

正在播放歌曲显示

//通过信号与槽机制检测文件是否变化
void Widget::onDurationChanged(qint64 duration) //文件时长变化,更新当前播放文件名显示播放文件数据总大小的信号, 它可以获得文件时间长度。
{ui->horizontalSlider->setMaximum(duration); //设置进度条最大值 也就是歌曲时长 msint m_Value=playlist->currentIndex();//获取当前歌曲的位置QTextBlock textLine=doc->findBlockByNumber (m_Value) ;//获取当前文本中的一段QString str=textLine.text();//将获取后的数据转为字符串int fi=0,af=9;QString s;if(str[0]=='D')//判断是否为本地文件(我的歌是在D盘里面的,所以第一个字符是D){while(str[af]!='\0'){s[fi]=str[af];fi++;af++;}s[fi]='\0';ui->lineEdit->setText(s);}elseui->lineEdit->setText(str);
}

进度条显示

void Widget::onPositionChanged(qint64 position)//当前文件播放位置变化,更新进度显示播放到什么位置的信号, 参数是以毫秒来计算的。
{if(ui->horizontalSlider->isSliderDown())return;//如果手动调整进度条,则不处理ui->horizontalSlider->setSliderPosition(position);//设置进度条的位置
}

搜索歌曲ID


void Widget::on_b_search_clicked()
{ui->music_m->clear();QString str,s;s=ui->l_search->text();//获取在搜索框输入的数据str="http://music.163.com/api/search/get/web?csrf_token=hlpretag=&hlposttag=&s={"+s+"}&type=1&offset=0&total=true&limit=1";//接入网易云API并且传入需要搜索的数据和返回的数量QNetworkRequest request;          //定义一个请求对象request.setUrl(str);      //将请求格式设置给请求对象manager->get(request);              //请求}

解析返回的数据

void Widget::databack(QNetworkReply *reply)
{searchInfo=reply->readAll();    //读取返回的全部数据QJsonParseError err;               //错误信息对象QJsonDocument json_recv = QJsonDocument::fromJson(searchInfo,&err);//将json文本转换为 json 文件对象if(err.error != QJsonParseError::NoError)             //判断是否符合语法{qDebug() <<"搜索歌曲Json获取格式错误"<< err.errorString();return;}QJsonObject totalObject = json_recv.object();QStringList keys = totalObject.keys();    // 列出json里所有的keyif(keys.contains("result"))                 //如果有结果{       //在 json 文本中 {}花括号里面是QJsonObject对象, []方括号里面是QJsonArrayQJsonObject resultObject = totalObject["result"].toObject();     //就将带 result 的内容提取后转换为对象QStringList resultKeys = resultObject.keys();      //保存所有keyif(resultKeys.contains("songs"))                    //如果 key 为songs ,代表找到了歌曲{QJsonArray array = resultObject["songs"].toArray();for(auto i : array)                   //开始获取歌曲中的信息{QJsonObject object = i.toObject();musicId = object["id"].toInt();                         // 音乐idmusicDuration = object["duration"].toInt();             // 音乐长度musicName = object["name"].toString();                  // 音乐名mvId = object["mvid"].toInt();                          // mvidQStringList 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();            // 专辑名}ui->music_m->appendPlainText("音乐ID:"+QString::number(musicId));ui->music_m->appendPlainText("音乐名:"+musicName);ui->music_m->appendPlainText("歌手名:"+singerName);ui->music_m->appendPlainText("总时长:"+QString::number(musicDuration));ui->music_m->appendPlainText("专辑名:"+albumName);}}}QString url;url=QString("https://music.163.com/song/media/outer/url?id=%0").arg(musicId);//通过网网易云API传入之前返回的歌曲的ID实现播放playlist->addMedia(QUrl(url)); //添加一音乐到播放列表中ui->plainTextEdit->appendPlainText(musicName); //用于显示
}

遇到的问题:

1.网易云的API(自己在网上找的)

有关评论
http://music.163.com/api/v1/resource/comments/R_SO_4_{歌曲ID}?limit=20&offset=0
limit:返回数据条数(每页获取的数量),默认为20,可以自行更改
offset:偏移量(翻页),offset需要是limit的倍数
type:搜索的类型歌单
https://music.163.com/api/playlist/detail?id={歌单ID}
网易云音乐每日推荐各种神奇歌单也是它的一大特色,我们可以利用这个api获取歌单里的所有歌曲信息。用户信息
https://music.163.com/api/v1/user/detail/{用户ID}歌词
https://music.163.com/api/song/lyric?id={歌曲ID}&lv=1&kv=1&tv=-1搜索结果
http://music.163.com/api/search/get/web?csrf_token=hlpretag=&hlposttag=&s={搜索内容}&type=1&offset=0&total=true&limit=20
limit:返回数据条数(每页获取的数量),默认为20,可以自行更改
offset:偏移量(翻页),offset需要是limit的倍数
type:搜索的类型
type=1           单曲
type=10         专辑
type=100        歌手
type=1000      歌单
type=1002      用户
type=1004      MV
type=1006      歌词
type=1009      主播电台歌手专辑
http://music.163.com/api/artist/albums/{歌手ID}?id={歌手ID}&offset=0&total=true&limit=10专辑信息
http://music.163.com/api/album/{专辑ID}?ext=true&id={专辑ID}&offset=0&total=true&limit=10歌曲信息
http://music.163.com/api/song/detail/?id={歌曲ID}&ids=%5B{歌曲ID}%5DMV
http://music.163.com/api/mv/detail?id={MV的ID}&type=mp4

2.可能报的错

qt.network.ssl: QSslSocket::connectToHostEncrypted: TLS initialization failed
大致说,Qt模块中是包含了OpenSSL库的,但是这些库不会自动部署到应用程序中。开发人员希望使用SSL的同时,它们的用户也安装了相关库。或者确保在当地使用SSL是经过许可
可以安装opssl解决doRender: Unknown error 0x80040218.
可能是因为没有装解码组件可以去安装一个 LAVFilters:
也可能是因为播放的音乐是VIP音乐(播放VIP音乐就会报这个错)

效果视频单独发布了(用的那个游戏盒子录的屏,跳出来的文件夹没有显示)

源码

widget.h

#ifndef WIDGET_H
#define WIDGET_H#include <QWidget>
#include <QMediaPlayer>
#include <QMediaPlaylist>
#include <QList>
#include <QMediaContent>
#include <QTextBlock>
#include <QTimer>
#include <QNetworkAccessManager>
#include <QNetworkReply>
#include <QJsonParseError>
#include <QJsonObject>
#include <QJsonArray>
#include <QMessageBox>QT_BEGIN_NAMESPACE
namespace Ui { class Widget; }
QT_END_NAMESPACEclass Widget : public QWidget
{Q_OBJECTpublic:Widget(QWidget *parent = nullptr);~Widget();public slots:void on_pushButton_2_clicked();void on_pushButton_clicked();void on_next_clicked();void on_up_clicked();void timechange(qint64 duration);void onDurationChanged(qint64 duration); void onPositionChanged(qint64 position); void on_b_search_clicked();void databack(QNetworkReply *reply);private:Ui::Widget *ui;QString durationTime;QString positionTime;QNetworkAccessManager* manager;QMediaPlayer *player;QMediaPlaylist *playlist;QString file;QTextDocument* doc;QTextBlock textLine;QString str;int i,x;int musicId,musicDuration,mvId;QString musicName,singerName,albumName;QByteArray searchInfo;
};
#endif // WIDGET_H

widget.cpp

#include "widget.h"
#include "ui_widget.h"#include <QFileDialog>
#include <QDir>
#include <QFile>
#include <QLCDNumber>
#include <QString>
#include <QBrush>Widget::Widget(QWidget *parent): QWidget(parent), ui(new Ui::Widget)
{ui->setupUi(this);this->setMinimumSize(600,600);this->setMaximumSize(600,600);//我固定了窗口的大小ui->music_m->setReadOnly(true);//将显示信息的组件设置设置为只读manager = new QNetworkAccessManager(this);   //定义并实例化一个网络管家ui->plainTextEdit->setReadOnly(true);//将显示音乐列表的组件设置为只读ui->lineEdit->setReadOnly(true);//将显示正在播放音乐的组件设置为只读this->setWindowTitle("QT播放器");//设置窗口标题x=0;//初始化标志位doc=ui->plainTextEdit->document () ; //文本对象player=new QMediaPlayer(this);playlist=new QMediaPlaylist(this);//初始化对象player->setMedia(playlist);//设置播放列表playlist->setPlaybackMode(QMediaPlaylist::Loop);设置播放模式//信号与槽机制进行处理connect(player,SIGNAL(positionChanged(qint64)),this,SLOT(timechange(qint64)));connect(player,SIGNAL(positionChanged(qint64)),this,SLOT(onPositionChanged(qint64)));connect(player,SIGNAL(durationChanged(qint64)),this,SLOT(onDurationChanged(qint64)));connect(manager,SIGNAL(finished(QNetworkReply *)),this,SLOT(databack(QNetworkReply *)));}Widget::~Widget()
{delete ui;
}void Widget::on_pushButton_2_clicked()
{file = QFileDialog::getOpenFileName(this,"Open File","D:/Music","mp3 Files (*.mp3)");//打开文件playlist->addMedia(QUrl(file));//将选中的MP3文件添加到播放列表//将选中的文件去掉路径后追加显示到plainTextEditint fi=0,af=9;QString s;while(file[af]!='\0'){s[fi]=file[af];fi++;af++;}s[fi]='\0';ui->plainTextEdit->appendPlainText(s);}void Widget::on_pushButton_clicked()
{if(x==0)   //如果是停止状态或暂停就播放{player->play();x=1;}else if(x==1)         //如果是播放状态就暂停{player->pause();x=0;}
}void Widget::on_next_clicked()
{int m_Value=playlist->currentIndex();//当前歌曲是第几个int m_Amount=playlist->mediaCount();   //总歌曲数量if(m_Value<m_Amount){m_Value=m_Value+1;playlist->setCurrentIndex(m_Value);player->play();}else{m_Value=0;playlist->setCurrentIndex(m_Value);player->play();}}void Widget::on_up_clicked()
{int m_Value=playlist->currentIndex();//当前歌曲是第几个int m_Amount=playlist->mediaCount();   //总歌曲数量if(m_Value>0){m_Value=m_Value-1;playlist->setCurrentIndex(m_Value);player->play();}else{m_Value=m_Amount-1;playlist->setCurrentIndex(m_Value);player->play();}
}
void Widget::timechange(qint64 duration)
{int secs = duration/1000; //全部秒数int mins = secs/60;//分secs = secs % 60;//秒QString str=QString::asprintf("%d:%d",mins,secs);ui->lcdNumber->display(str);
}void Widget::onDurationChanged(qint64 duration) //文件时长变化,更新当前播放文件名显示播放文件数据总大小的信号, 它可以获得文件时间长度。
{ui->horizontalSlider->setMaximum(duration); //设置进度条最大值 也就是歌曲时长 msint m_Value=playlist->currentIndex();QTextBlock textLine=doc->findBlockByNumber (m_Value) ; // 文本中的一段QString str=textLine.text();int fi=0,af=9;QString s;if(str[0]=='D'){while(str[af]!='\0'){s[fi]=str[af];fi++;af++;}s[fi]='\0';ui->lineEdit->setText(s);}elseui->lineEdit->setText(str);
}
void Widget::onPositionChanged(qint64 position)//当前文件播放位置变化,更新进度显示播放到什么位置的信号, 参数是以毫秒来计算的。
{if(ui->horizontalSlider->isSliderDown())return;//如果手动调整进度条,则不处理ui->horizontalSlider->setSliderPosition(position);
}void Widget::on_b_search_clicked()
{ui->music_m->clear();QString str,s;s=ui->l_search->text();str="http://music.163.com/api/search/get/web?csrf_token=hlpretag=&hlposttag=&s={"+s+"}&type=1&offset=0&total=true&limit=1";QNetworkRequest request;          //定义一个请求对象request.setUrl(str);      //将请求格式设置给请求对象manager->get(request);              //请求}
void Widget::databack(QNetworkReply *reply)
{searchInfo=reply->readAll();QJsonParseError err;               //错误信息对象QJsonDocument json_recv = QJsonDocument::fromJson(searchInfo,&err);//将json文本转换为 json 文件对象if(err.error != QJsonParseError::NoError)             //判断是否符合语法{qDebug() <<"搜索歌曲Json获取格式错误"<< err.errorString();return;}QJsonObject totalObject = json_recv.object();QStringList keys = totalObject.keys();    // 列出json里所有的keyif(keys.contains("result"))                 //如果有结果{       //在 json 文本中 {}花括号里面是QJsonObject对象, []方括号里面是QJsonArrayQJsonObject resultObject = totalObject["result"].toObject();     //就将带 result 的内容提取后转换为对象QStringList resultKeys = resultObject.keys();      //保存所有keyif(resultKeys.contains("songs"))                    //如果 key 为songs ,代表找到了歌曲{QJsonArray array = resultObject["songs"].toArray();for(auto i : array)                   //开始获取歌曲中的信息{QJsonObject object = i.toObject();musicId = object["id"].toInt();                         // 音乐idmusicDuration = object["duration"].toInt();             // 音乐长度musicName = object["name"].toString();                  // 音乐名mvId = object["mvid"].toInt();                          // mvidQStringList 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();            // 专辑名}ui->music_m->appendPlainText("音乐ID:"+QString::number(musicId));ui->music_m->appendPlainText("音乐名:"+musicName);ui->music_m->appendPlainText("歌手名:"+singerName);ui->music_m->appendPlainText("总时长:"+QString::number(musicDuration));ui->music_m->appendPlainText("专辑名:"+albumName);}}}QString url;url=QString("https://music.163.com/song/media/outer/url?id=%0").arg(musicId);playlist->addMedia(QUrl(url));                     //添加返回的音乐到播放列表中ui->plainTextEdit->appendPlainText(musicName); //用于显示
}

QT音乐播放器(接入网易云API)相关推荐

  1. Qt音乐播放器实现(带歌词功能)

    最近期末项目要写一个音乐播放器,作为新人头疼了好久,参考了各方文档,总算憋出来了一个,歌词功能用的是一个大佬实现的,然后我就调用了,就是我那个lyricwidget.cpp和头文件就是直接弄过来的,但 ...

  2. 基于Qt的在线音乐播放器

    1.了解音乐播放器应该有哪些功能: 音乐播放器的各种控制(上下曲,单曲循环,随机播放,顺序播放),歌曲列表,歌词显示,本地音乐保存,在线音乐搜索,在线音乐播放. 2.制作Qt音乐播放器一定要了解Qme ...

  3. Qt项目:基与Qt的音乐播放器(本地)

    目录 1.类中添加基本的成员 2.实现音频文件的对话框和实现音乐的播放功能 3.切换歌曲 4.播放/暂停 5.音量相关功能 6.调节语速 7. 实现进度条更新以及文件时长显示 8.双击播放自己选中的音 ...

  4. 自学QT之简易音乐播放器基于QT5.5

    自己写的音乐播放器,还存在很多bug,只是作为一种尝试而已.交流学习群:271251545 播放器实现的功能:添加歌曲.上一首.暂停.下一首.切换歌曲.托盘.任务栏对歌曲进行操作 界面偷懒,直接使用的 ...

  5. 【C++】QT制作简单音乐播放器

    QT音乐播放器Mymusic 整体布局 写ui文件: Headers Sources 整体布局 创建QT项目,使用Qt5.9版本 分为三栏,最上面放标题和图标,中间放播放的列表,最下面放控制按钮. 引 ...

  6. QT 基于 百度云语音识别, 基于网易API 接口的歌曲查询,的音乐播放器。

    1.成果展示: 2.界面操作提示 1.  2种方法把歌曲加入列表, 第一种加入本地资源,第二种 加入网上搜索的歌曲 2.  加入本地资源,点击图片  +  ,然后再本地资源里面添加歌曲 3.  网上搜 ...

  7. 基于Qt的网络音乐播放器(四)酷狗API接口获取歌曲的搜索列表和歌曲的播放

    2020博客之星年度总评选进行中:请为74号的狗子投上宝贵的一票! 我的投票地址:点击为我投票 文章目录 1.效果图 2.准备好前面获取的酷狗api接口 3.网络歌曲搜索实现 4.网络歌曲播放的实现 ...

  8. 【QT】实现本地音乐播放器

    [说明]最近在写一个音乐播放器,大概花了两天时间完成了基本功能,包括本地音乐的打开.播放.收藏等.后续想完善音乐列表(借助sqlite数据库).网络音乐(借助网易云API接口)功能,先上初步UI效果图 ...

  9. 基于Qt的音乐播放器制作

    基于Qt的音乐播放器制作 使用浏览器自带工具抓包歌曲资源 开发人员工具抓包 点击浏览器右上角的 "-" 快捷键(Alt + F): 点击其中的"更多工具" ➡ ...

  10. 基于Qt的仿酷狗音乐播放器设计(一)

    简述 其实在很早以前博主就有想用Qt写一个比较好的音乐播放器的想法,但由于平时上课的压力和以前对设计模式和代码规范做的不太好,一直没有进行.所以在这个寒假准备好好的设计一下.下面先简单的说明一下设计的 ...

最新文章

  1. Flask Vue.js全栈开发
  2. ad采集 cube配置 dma_【技术技巧】 使用MCC数据采集设备获取模拟波形
  3. 端口报错listen eaddrinuse:::xxx
  4. jni加载第三方so_Linux的so文件到底是干嘛的?浅析Linux的动态链接库
  5. C#中不常见的运算符功能汇总
  6. eclipse plugin 菜单
  7. screenfetch 和 linux_logo安装使用
  8. idea删除不用或者失效的jdk
  9. 【时间序列分析】03.正态时间序列与严平稳序列
  10. 数据湖统一存储在 OPPO 的实践
  11. vs2019 C#提示程序未兼容
  12. 网络市场与群体练习题
  13. Win10物理机的VMnet8和VMnet1黄色感叹号
  14. 王者荣耀微信查看服务器地址大全,王者荣耀微信如何查找自己所在大区 | 手游网游页游攻略大全...
  15. 2020.6.7日笔记
  16. 【电商】电商后台系统整体介绍
  17. vue3-父子组件间通信
  18. OpenMLDB 开源一周年,感恩遇见
  19. 2015 读书笔记--告诉我你怎样去生活
  20. IR VS功率器件常备现货型号

热门文章

  1. C/C++ Linux 异步IO(AIO)
  2. 数据库课程设计报告总结
  3. 在国内使用DNS服务器的一个对比分析
  4. DuFile网赚网盘
  5. android xml 注释快捷键,xml注释(xml注释掉一段代码)
  6. 科学计算机解方程算法,数值方法解方程之终极算法
  7. JSON转换问题最全详解(json转List,json转对象,json转JSONObject)
  8. java实现modbus rtu协议与 modscan等工具(4)rtu转tcp
  9. 《算法导论》第三版第7章 快速排序 练习思考题 个人答案
  10. Tomcat、Servlet、Servlet容器