当前位置:   article > 正文

libVLC 音频立体声模式切换

libVLC 音频立体声模式切换

在libVLC中,可以使用libvlc_audio_set_channel函数来设置音频的立体声模式。这个函数允许选择不同的音频通道,例如立体声、左声道、右声道、环绕声等。

  1. /**
  2. * Set current audio channel.
  3. *
  4. * \param p_mi media player
  5. * \param channel the audio channel, \see libvlc_audio_output_channel_t
  6. * \return 0 on success, -1 on error
  7. */
  8. LIBVLC_API int libvlc_audio_set_channel( libvlc_media_player_t *p_mi, int channel );

参数说明:

  • p_mi:媒体播放器实例。
  • channel:要设置的音频通道,是一个 libvlc_audio_output_channel_t 类型的枚举值。

返回值是一个整数,如果设置成功则返回 0,如果设置失败则返回一个负数。

的可能值包括:

  1. /**
  2. * Audio channels
  3. */
  4. typedef enum libvlc_audio_output_channel_t {
  5. libvlc_AudioChannel_Error = -1, //错误通道
  6. libvlc_AudioChannel_Stereo = 1, //立体声
  7. libvlc_AudioChannel_RStereo = 2, //翻转立体声
  8. libvlc_AudioChannel_Left = 3, //左声道
  9. libvlc_AudioChannel_Right = 4, //右声道
  10. libvlc_AudioChannel_Dolbys = 5 //杜比环绕声
  11. } libvlc_audio_output_channel_t;

以下是VLC播放器中使用的视频裁剪,我们仿照这个做一个界面。  

以下是做出来的效果:

首先做一个菜单:

  1. QMenu *m_moduleMenu = nullptr; //立体声模式菜单
  2. QAction *m_actionModule = nullptr; //立体声模式
  3. QAction *m_actionMono = nullptr;//单声道
  4. QAction *m_actionStereo = nullptr;//立体声
  5. QAction *m_actionLeft = nullptr;//左声道
  6. QAction *m_actionRight = nullptr;//右声道
  7. QAction *m_actionRevStereo = nullptr;//反转立体声
  8. m_moduleMenu = new QMenu(this);
  9. m_actionMono = m_moduleMenu->addAction("单声道");
  10. m_actionMono->setData((int)libvlc_AudioChannel_Dolbys);
  11. m_actionStereo = m_moduleMenu->addAction("立体声");
  12. m_actionStereo->setData((int)libvlc_AudioChannel_Stereo);
  13. m_actionLeft = m_moduleMenu->addAction("左声道");
  14. m_actionLeft->setData((int)libvlc_AudioChannel_Left);
  15. m_actionRight = m_moduleMenu->addAction("右声道");
  16. m_actionRight->setData((int)libvlc_AudioChannel_Right);
  17. m_actionRevStereo = m_moduleMenu->addAction("反转立体声");
  18. m_actionRevStereo->setData((int)libvlc_AudioChannel_RStereo);
  19. m_actionModule->setMenu(m_moduleMenu);

接受槽函数的响应事件:

  1. void showWidget::slotActionModuleTriggered(QAction *action)
  2. {
  3. if (!vlc_mediaPlayer)
  4. return;
  5. libvlc_audio_output_channel_t channel = (libvlc_audio_output_channel_t)action->data().toInt();
  6. int cc = libvlc_audio_set_channel(vlc_mediaPlayer, channel);
  7. action->setIcon(QIcon(":/image/images/point.png"));
  8. m_preAction->setIcon(QIcon());
  9. m_preAction = action;
  10. }

设置鼠标右键弹出菜单:重写鼠标点击事件,弹出菜单。

首先设置libvlc忽略鼠标事件libvlc_video_set_mouse_input(vlc_mediaPlayer, 0);

再重写鼠标事件:

  1. void showWidget::mousePressEvent(QMouseEvent *event)
  2. {
  3. switch (event->button())
  4. {
  5. case Qt::RightButton:
  6. //this->setWindowState(Qt::WindowMinimized);
  7. m_menu->exec(event->globalPos());
  8. break;
  9. default:
  10. QWidget::mousePressEvent(event);
  11. }
  12. }

完整代码:

头文件。

  1. #pragma once
  2. #include <QtWidgets/QWidget>
  3. #include "ui_showWidget.h"
  4. #include <QMenu>
  5. #include <QActionGroup>
  6. #include <vlc/vlc.h>
  7. #include <QDebug>
  8. #include <QFileDialog>
  9. #include <QThread>
  10. #include <QMouseEvent>
  11. #include <QKeyEvent>
  12. enum Rate
  13. {
  14. Rate2X,
  15. Rate1_5X,
  16. Rate1_25X,
  17. Rate1_0X,
  18. Rate0_75X,
  19. Rate0_5X
  20. };
  21. class showWidget : public QWidget
  22. {
  23. Q_OBJECT
  24. public:
  25. showWidget(QWidget *parent = nullptr);
  26. ~showWidget();
  27. private slots:
  28. void slotOpenFile();
  29. void slotPlay();
  30. void slotPause();
  31. void slotStop();
  32. void slotValueChanged(int value);
  33. void slotCurrentIndexChanged(int index);
  34. void slotActionTriggered(QAction *action);
  35. void slotActionModuleTriggered(QAction *action);
  36. protected:
  37. virtual void mousePressEvent(QMouseEvent *event);
  38. private:
  39. //事件处理回调
  40. static void vlcEvents(const libvlc_event_t *ev, void *param);
  41. private:
  42. Ui::showWidgetClass ui;
  43. private:
  44. libvlc_instance_t *vlc_base = nullptr;
  45. libvlc_media_t *vlc_media = nullptr;
  46. libvlc_media_player_t *vlc_mediaPlayer = nullptr;
  47. QList<float> m_lstRate;
  48. QList<QString> m_lstAudioDevice;
  49. QMenu *m_menu = nullptr;
  50. QMenu *m_deviceMenu = nullptr; //音频设备菜单
  51. QMenu *m_moduleMenu = nullptr; //立体声模式菜单
  52. QAction *m_actionAudioDev = nullptr; //音频设备
  53. QAction *m_actionModule = nullptr; //立体声模式
  54. QAction *m_actionMono = nullptr;//单声道
  55. QAction *m_actionStereo = nullptr;//立体声
  56. QAction *m_actionLeft = nullptr;//左声道
  57. QAction *m_actionRight = nullptr;//右声道
  58. QAction *m_actionRevStereo = nullptr;//反转立体声
  59. QActionGroup *m_group = nullptr;
  60. QActionGroup *m_groupModule = nullptr;
  61. QAction *m_preAction = nullptr;
  62. };

cpp文件。 

  1. #include "showWidget.h"
  2. #include <QTimer>
  3. #include <QTime>
  4. #pragma execution_character_set("utf-8")
  5. showWidget::showWidget(QWidget *parent)
  6. : QWidget(parent)
  7. {
  8. ui.setupUi(this);
  9. this->setWindowTitle("视频播放器");
  10. m_menu = new QMenu(this);
  11. m_actionAudioDev = m_menu->addAction("音频设备");
  12. m_actionModule = m_menu->addAction("立体声模式");
  13. m_deviceMenu = new QMenu(this);
  14. m_actionAudioDev->setMenu(m_deviceMenu);
  15. m_moduleMenu = new QMenu(this);
  16. m_actionMono = m_moduleMenu->addAction("单声道");
  17. m_actionMono->setData((int)libvlc_AudioChannel_Dolbys);
  18. m_actionStereo = m_moduleMenu->addAction("立体声");
  19. m_actionStereo->setData((int)libvlc_AudioChannel_Stereo);
  20. m_actionLeft = m_moduleMenu->addAction("左声道");
  21. m_actionLeft->setData((int)libvlc_AudioChannel_Left);
  22. m_actionRight = m_moduleMenu->addAction("右声道");
  23. m_actionRight->setData((int)libvlc_AudioChannel_Right);
  24. m_actionRevStereo = m_moduleMenu->addAction("反转立体声");
  25. m_actionRevStereo->setData((int)libvlc_AudioChannel_RStereo);
  26. m_actionModule->setMenu(m_moduleMenu);
  27. m_group = new QActionGroup(this);
  28. connect(m_group, &QActionGroup::triggered, this, &showWidget::slotActionTriggered);
  29. m_groupModule = new QActionGroup(this);
  30. m_groupModule->addAction(m_actionMono);
  31. m_groupModule->addAction(m_actionStereo);
  32. m_groupModule->addAction(m_actionLeft);
  33. m_groupModule->addAction(m_actionRight);
  34. m_groupModule->addAction(m_actionRevStereo);
  35. connect(m_groupModule, &QActionGroup::triggered, this, &showWidget::slotActionModuleTriggered);
  36. vlc_base = libvlc_new(0, NULL);
  37. m_lstAudioDevice.clear();
  38. libvlc_audio_output_device_t *pDevList = nullptr;
  39. libvlc_audio_output_t *pOutputList = libvlc_audio_output_list_get(vlc_base);
  40. while (pOutputList)
  41. {
  42. //获取设备
  43. pDevList = libvlc_audio_output_device_list_get(vlc_base, pOutputList->psz_name);
  44. while (pDevList)
  45. {
  46. // 找到我想要的那个设备,跳出循环,这里使用i控制,我知道我想要的设备位置
  47. if (strcmp(pOutputList->psz_name, "mmdevice") == 0)
  48. {
  49. QString des = QString::fromStdString(std::string(pDevList->psz_description, strlen(pDevList->psz_description)));
  50. m_lstAudioDevice.append(des);
  51. QAction *action = m_deviceMenu->addAction(des);
  52. action->setData(pDevList->psz_device);
  53. m_group->addAction(action);
  54. }
  55. pDevList = pDevList->p_next;
  56. }
  57. pOutputList = pOutputList->p_next;
  58. }
  59. ui.cbxRate->setCurrentIndex(Rate1_0X);
  60. m_lstRate << 2.0 << 1.5 << 1.25 << 1.0 << 0.75 << 0.5;
  61. ui.btnOpen->setFocusPolicy(Qt::NoFocus);
  62. ui.btnPlay->setFocusPolicy(Qt::NoFocus);
  63. ui.btnPause->setFocusPolicy(Qt::NoFocus);
  64. ui.btnStop->setFocusPolicy(Qt::NoFocus);
  65. ui.hSliderVolumn->setFocusPolicy(Qt::NoFocus);
  66. ui.cbxRate->setFocusPolicy(Qt::NoFocus);
  67. connect(ui.btnOpen, &QPushButton::clicked, this, &showWidget::slotOpenFile);
  68. connect(ui.btnPlay, &QPushButton::clicked, this, &showWidget::slotPlay);
  69. connect(ui.btnPause, &QPushButton::clicked, this, &showWidget::slotPause);
  70. connect(ui.btnStop, &QPushButton::clicked, this, &showWidget::slotStop);
  71. connect(ui.hSliderVolumn, &QSlider::valueChanged, this, &showWidget::slotValueChanged);
  72. connect(ui.cbxRate,SIGNAL(currentIndexChanged(int)), this, SLOT(slotCurrentIndexChanged(int)));
  73. }
  74. showWidget::~showWidget()
  75. {
  76. libvlc_release(vlc_base); //减少libvlc实例的引用计数,并销毁
  77. }
  78. void showWidget::slotOpenFile()
  79. {
  80. /*选择文件*/
  81. QString filename = QFileDialog::getOpenFileName(this, "选择打开的文件", "D:/", tr("*.*"));
  82. std::replace(filename.begin(), filename.end(), QChar('/'), QChar('\\'));
  83. vlc_media = libvlc_media_new_path(vlc_base, filename.toUtf8().data());
  84. if (!vlc_media) {
  85. return;
  86. }
  87. // 创建libvlc实例和媒体播放器
  88. vlc_mediaPlayer = libvlc_media_player_new_from_media(vlc_media);
  89. if (!vlc_mediaPlayer) {
  90. return;
  91. }
  92. //libvlc_media_add_option(vlc_media, "--video-filter=transform");
  93. //libvlc_media_add_option(vlc_media, "---transform-type=270");
  94. // 等待元数据加载完成
  95. libvlc_media_parse(vlc_media);
  96. libvlc_video_set_mouse_input(vlc_mediaPlayer, 0);
  97. libvlc_video_set_key_input(vlc_mediaPlayer, 0);
  98. // 获取各种元数据
  99. const char *title = libvlc_media_get_meta(vlc_media, libvlc_meta_Title);
  100. const char *artist = libvlc_media_get_meta(vlc_media, libvlc_meta_Artist);
  101. const char *album = libvlc_media_get_meta(vlc_media, libvlc_meta_Album);
  102. const char *url = libvlc_media_get_meta(vlc_media, libvlc_meta_URL);
  103. const char *date = libvlc_media_get_meta(vlc_media, libvlc_meta_Date);
  104. const char *lang = libvlc_media_get_meta(vlc_media, libvlc_meta_Language);
  105. int duration = libvlc_media_get_duration(vlc_media); // 获取时长(单位:毫秒)
  106. qDebug("Title: %s", title ? title : "N/A");
  107. qDebug("Artist: %s", artist ? artist : "N/A");
  108. qDebug("Album: %s", album ? album : "N/A");
  109. qDebug("Duration: %d ms", duration);
  110. qDebug("url: %s", url ? url : "N/A");
  111. qDebug("date: %s", date ? date : "N/A");
  112. qDebug("lang: %s", lang ? lang : "N/A");
  113. libvlc_media_track_t **tracks;
  114. int track_count = libvlc_media_tracks_get(vlc_media,&tracks);
  115. for (unsigned i = 0; i < track_count; i++)
  116. {
  117. libvlc_media_track_t* track = tracks[i];
  118. // 显示轨道信息
  119. printf("Track #%u: %s\n", i, track->psz_description);
  120. // 这里可以获取到每一个轨道的信息,比如轨道类型 track->i_type
  121. // 可能是 libvlc_track_video, libvlc_track_audio 或者 libvlc_track_text (字幕)
  122. if (track->i_type == libvlc_track_video) {
  123. // 处理视频轨道信息
  124. qDebug("width = %d",track->video->i_width);
  125. qDebug("height = %d", track->video->i_height);
  126. qDebug("rate_num = %d", track->video->i_frame_rate_num);
  127. qDebug("rate_den = %d", track->video->i_frame_rate_den);
  128. }
  129. else if (track->i_type == libvlc_track_audio) {
  130. // 处理音频轨道信息
  131. qDebug("channels = %d", track->audio->i_channels);
  132. qDebug("rate = %d", track->audio->i_rate);
  133. }
  134. else if (track->i_type == libvlc_track_text) {
  135. // 处理字幕轨道信息
  136. }
  137. }
  138. //获取事件管理器
  139. libvlc_event_manager_t *em = libvlc_media_player_event_manager(vlc_mediaPlayer);
  140. // 注册事件监听器
  141. libvlc_event_attach(em, libvlc_MediaPlayerTimeChanged, vlcEvents, this);
  142. libvlc_event_attach(em, libvlc_MediaPlayerEndReached, vlcEvents, this);
  143. libvlc_event_attach(em, libvlc_MediaPlayerStopped, vlcEvents, this);
  144. libvlc_event_attach(em, libvlc_MediaPlayerPlaying, vlcEvents, this);
  145. libvlc_event_attach(em, libvlc_MediaPlayerPaused, vlcEvents, this);
  146. libvlc_media_player_set_hwnd(vlc_mediaPlayer, (void *)ui.widgetShow->winId());
  147. libvlc_video_set_adjust_int(vlc_mediaPlayer, libvlc_adjust_Enable, 1);
  148. //获取当前的channel
  149. int curChannel = libvlc_audio_get_channel(vlc_mediaPlayer);
  150. m_actionStereo->setIcon(QIcon(":/image/images/point.png"));
  151. m_preAction = m_actionStereo;
  152. QTimer::singleShot(1000, this, &showWidget::slotPlay);
  153. libvlc_video_filter_list_get(vlc_base);
  154. }
  155. void showWidget::slotPlay()
  156. {
  157. if (vlc_mediaPlayer)
  158. {
  159. libvlc_media_player_play(vlc_mediaPlayer);
  160. }
  161. }
  162. void showWidget::slotPause()
  163. {
  164. if (vlc_mediaPlayer)
  165. libvlc_media_player_pause(vlc_mediaPlayer);
  166. }
  167. void showWidget::slotStop()
  168. {
  169. if (vlc_mediaPlayer)
  170. libvlc_media_player_stop(vlc_mediaPlayer);
  171. }
  172. void showWidget::slotValueChanged(int value)
  173. {
  174. if (vlc_mediaPlayer)
  175. libvlc_audio_set_volume(vlc_mediaPlayer, value);
  176. }
  177. void showWidget::slotCurrentIndexChanged(int index)
  178. {
  179. if (vlc_mediaPlayer)
  180. libvlc_media_player_set_rate(vlc_mediaPlayer, m_lstRate[index]);
  181. }
  182. void showWidget::slotActionTriggered(QAction *action)
  183. {
  184. if (!vlc_mediaPlayer)
  185. return;
  186. QString txt = action->data().toString();
  187. //指定设备输出pDevList->psz_device
  188. libvlc_audio_output_device_set(vlc_mediaPlayer, NULL, txt.toStdString().c_str());
  189. }
  190. void showWidget::slotActionModuleTriggered(QAction *action)
  191. {
  192. if (!vlc_mediaPlayer)
  193. return;
  194. libvlc_audio_output_channel_t channel = (libvlc_audio_output_channel_t)action->data().toInt();
  195. int cc = libvlc_audio_set_channel(vlc_mediaPlayer, channel);
  196. action->setIcon(QIcon(":/image/images/point.png"));
  197. m_preAction->setIcon(QIcon());
  198. m_preAction = action;
  199. }
  200. void showWidget::mousePressEvent(QMouseEvent *event)
  201. {
  202. switch (event->button())
  203. {
  204. case Qt::RightButton:
  205. //this->setWindowState(Qt::WindowMinimized);
  206. m_menu->exec(event->globalPos());
  207. break;
  208. default:
  209. QWidget::mousePressEvent(event);
  210. }
  211. }
  212. //事件回调
  213. void showWidget::vlcEvents(const libvlc_event_t *ev, void *param)
  214. {
  215. showWidget *w = (showWidget*)param;
  216. //处理不同的事件
  217. switch (ev->type) {
  218. case libvlc_MediaPlayerTimeChanged:
  219. {
  220. //qDebug() << "VLC媒体播放器时间已更改";
  221. qint64 len = libvlc_media_player_get_time(w->vlc_mediaPlayer);
  222. libvlc_time_t lenSec = len / 1000;
  223. libvlc_time_t totalLen = libvlc_media_player_get_length(w->vlc_mediaPlayer);
  224. libvlc_time_t totalLenSec = totalLen / 1000;
  225. int thh, tmm, tss;
  226. thh = lenSec / 3600;
  227. tmm = (lenSec % 3600) / 60;
  228. tss = (lenSec % 60);
  229. QTime time(thh, tmm, tss);
  230. w->ui.lbCurTime->setText(time.toString("hh:mm:ss"));
  231. thh = totalLenSec / 3600;
  232. tmm = (totalLenSec % 3600) / 60;
  233. tss = (totalLenSec % 60);
  234. QTime TotalTime(thh, tmm, tss);
  235. w->ui.lbTotalTime->setText(TotalTime.toString("hh:mm:ss"));
  236. double pos = (double)lenSec / totalLenSec * 100;
  237. w->ui.horizontalSlider->setValue(pos);
  238. }
  239. break;
  240. case libvlc_MediaPlayerEndReached:
  241. qDebug() << "VLC播放完毕.";
  242. break;
  243. case libvlc_MediaPlayerStopped:
  244. qDebug() << "VLC停止播放";
  245. break;
  246. case libvlc_MediaPlayerPlaying:
  247. qDebug() << "VLC开始播放";
  248. break;
  249. case libvlc_MediaPlayerPaused:
  250. qDebug() << "VLC暂停播放";
  251. break;
  252. }
  253. }

更多参考:

libVLC 事件机制-CSDN博客

libVLC windows开发环境搭建-CSDN博客

libVLC 元数据-CSDN博客

libVLC 添加图片和文本水印-CSDN博客

libVLC 音频输出设备切换-CSDN博客

声明:本文内容由网友自发贡献,不代表【wpsshop博客】立场,版权归原作者所有,本站不承担相应法律责任。如您发现有侵权的内容,请联系我们。转载请注明出处:https://www.wpsshop.cn/w/AllinToyou/article/detail/393289
推荐阅读
相关标签
  

闽ICP备14008679号