c#音乐播放器续(联网下载)

音乐播放器

  • 0.前言
  • 1.关于本地音乐播放
  • [2.使用iTunes Search API进行联网下载歌曲](#2.使用iTunes Search API进行联网下载歌曲)
    • [2.1 控件](#2.1 控件)
    • [2.2 函数实现](#2.2 函数实现)
      • [2.2.1 控件2:搜索歌曲](#2.2.1 控件2:搜索歌曲)
      • [2.2.2 控件3:下载歌曲](#2.2.2 控件3:下载歌曲)
    • [2.3 主界面](#2.3 主界面)
  • 3.拓展

0.前言

  • 书接上文,我们已经实现了一个能够播放本地音乐的音乐播放器,能够播放众多音乐格式,包括.ogg,接下来,我们将为我们的音乐播放器添加一个令人激动的新功能------联网音乐下载和播放!这个功能将使我们能够通过网络获取音乐,并将其添加到我们的播放列表中。
  • 为了实现这个功能,我们选择使用苹果音乐开放的API。尽管这个API只支持音乐的30秒预览,但它非常适合初学者上手。使用这个API不需要认证或密钥等额外操作,让我们能够更快地理解和实现联网音乐下载功能。
  • 本项目旨在练习如何实现联网音乐下载,理解基础方法后,想要拓展很快就能上手。

1.关于本地音乐播放

详情可查看本人上篇博客~

在此只放框架:

csharp 复制代码
public partial class Form1 : Form
{
    VorbisWaveReader oggReader = null;  //定义此对象,用于解析.ogg文件格式
    WaveOutEvent outputDevice = null;  //定义此对象,用于播放.ogg音频
    List<string> localmusiclist  = new List<string>(); //添加的所有音频文件
    int index = -1; //当前播放的音频文件索引
    public Form1()
 	{
     	InitializeComponent();
 	}
   private void musicplay(string filename)
   {
       label1.Text = Path.GetFileNameWithoutExtension(localmusiclist[index]);
       //获取filename的后缀名
       string extension = Path.GetExtension(filename).ToLower();
       //如果oggReader和outputDevice不为空,说明正在播放或播放过ogg文件,此时要再播放新选择的文件就要先释放旧的
       if (oggReader != null && outputDevice != null)
       {
           oggReader.Dispose();
           oggReader = null;
           outputDevice.Dispose(); 
           outputDevice = null;
       }
       axWindowsMediaPlayer1.Ctlcontrols.stop();
       try
       {
           if (extension == ".ogg")
           {
               oggReader = new VorbisWaveReader(filename);
               outputDevice = new WaveOutEvent();
               outputDevice.Init(oggReader);
               outputDevice.Play();
           }
           else
           {
               axWindowsMediaPlayer1.URL = filename;
               axWindowsMediaPlayer1.Ctlcontrols.play();
           }
       }
       catch (FileNotFoundException ex)
       {
           MessageBox.Show("File not found: " + ex.Message);
       }
       catch (Exception ex)
       {
           MessageBox.Show("An error occurred: " + ex.Message);
       }
   }
  //从本地添加歌曲
   private void button1_Click(object sender, EventArgs e)
   {
       OpenFileDialog openFileDialog1 = new OpenFileDialog();
       openFileDialog1.Filter = "选择音频|*.mp3;*.flac;*.wav;*.ogg";
       openFileDialog1.Multiselect = true;
       if(openFileDialog1.ShowDialog() == DialogResult.OK) 
       {
           string[] files = openFileDialog1.FileNames;
           foreach(string x in files)
           {
               listBox1.Items.Add(x);
               localmusiclist.Add(x);
           }
       }
   }
//点击音乐歌单事件,切换选择的歌曲
  private void listBox1_SelectedIndexChanged(object sender, EventArgs e)
  {
      if(localmusiclist.Count > 0)
      {
          index = listBox1.SelectedIndex;
          musicplay(localmusiclist[index]);
      }
  }
//音轨事件,用于响应调整声音
  private void trackBar1_Scroll(object sender, EventArgs e)
  {
      axWindowsMediaPlayer1.settings.volume = trackBar1.Value;
      if(outputDevice != null)
          outputDevice.Volume = trackBar1.Value;
  }
//暂停
  private void button2_Click(object sender, EventArgs e)
  {
      if(axWindowsMediaPlayer1 != null)
          axWindowsMediaPlayer1.Ctlcontrols.stop();
      if(outputDevice != null)
          outputDevice.Stop();
  }

//下一曲
  private void button3_Click(object sender, EventArgs e)
  {
      if(localmusiclist.Count > 0) 
      {
          index = (index+1)% localmusiclist.Count;
          musicplay(localmusiclist[index]);
          label1.Text = Path.GetFileNameWithoutExtension(localmusiclist[index]);
      }
  }

2.1 控件

  1. 控件1:输入歌曲搜索关键词
  2. 控件2:根据歌曲搜索关键词进行搜索,并显示于listBox2
  3. 控件3:下载listBox2选择的歌曲到本地
  4. 控件4:用于显示歌曲搜索出来的信息,并可以选择某首歌进行下载

2.2 函数实现

首先定义一个类的成员变量,用于网络连接

csharp 复制代码
private readonly HttpClient httpClient = new HttpClient();

2.2.1 控件2:搜索歌曲

csharp 复制代码
private async Task<List<string>> SearchMusic(string keyword)
{
    string apiUrl = $"https://itunes.apple.com/search?term={keyword}&media=music&limit=10";
    try
    {
        HttpResponseMessage response = await httpClient.GetAsync(apiUrl);
        response.EnsureSuccessStatusCode();

        string responseBody = await response.Content.ReadAsStringAsync();
        var json = JObject.Parse(responseBody);
        var results = json["results"];

        List<string> musicLinks = new List<string>();
        foreach (var result in results)
        {
            string trackName = result["trackName"].ToString();
            string artistName = result["artistName"].ToString();
            string previewUrl = result["previewUrl"].ToString();
            musicLinks.Add($"{trackName} - {artistName} | {previewUrl}");
            return musicLinks;
        }
    }
    catch (HttpRequestException e)
    {
        MessageBox.Show(e.Message);
    }
    catch (Exception ex)
    {
        MessageBox.Show($"Unexpected error: {ex.Message}");
    }
    return null;
    
}
private async void button4_Click(object sender, EventArgs e)
{

    string keyword = textBox1.Text.Trim();
    if (string.IsNullOrEmpty(keyword))
    {
        MessageBox.Show("请输入搜索关键词");
        return;
    }
    var results = await SearchMusic(keyword);
    if (results == null)
        return;           
    listBox2.Items.Clear();
    foreach (var result in results)
    {
        listBox2.Items.Add(result);
    }
}

在搜索歌曲的时候,一定要对结果判空,有可能什么也没搜到,这样会返回空
在操作控件时,对可能出错的步骤尽量使用异常处理的方法,这样即使出现错误也不会使主程序崩溃

2.2.2 控件3:下载歌曲

csharp 复制代码
private async Task DownloadMusic(string musicUrl, string filePath)
{
    HttpResponseMessage response = await httpClient.GetAsync(musicUrl);
    response.EnsureSuccessStatusCode();

    using (var fileStream = new FileStream(filePath, FileMode.Create, FileAccess.Write, FileShare.None))
    {
        await response.Content.CopyToAsync(fileStream);
    }
}
private async void button5_Click(object sender, EventArgs e)
{
    if (listBox2.SelectedItem == null)
    {
        MessageBox.Show("请选择要下载的音乐");
        return;
    }

    string selectedItem = listBox2.SelectedItem.ToString();
    string[] parts = selectedItem.Split('|');
    if (parts.Length < 2)
    {
        MessageBox.Show("无效的下载链接");
        return;
    }

    string musicUrl = parts[1].Trim();
    SaveFileDialog saveFileDialog = new SaveFileDialog();
    saveFileDialog.FileName = parts[0].Trim();
    saveFileDialog.Filter = "MP3 文件|*.mp3";
    if (saveFileDialog.ShowDialog() == DialogResult.OK)
    {
        string filePath = saveFileDialog.FileName;
        await DownloadMusic(musicUrl, filePath);
        MessageBox.Show("下载完成");
        //将下载好的歌曲直接添加到播放列表	
        listBox1.Items.Add(filePath);
        localmusiclist.Add(filePath);
    }
}

2.3 主界面



3.拓展

本项目使用的iTunes Search API肯定无法满足大家的需求

推荐一个比较好用的在线播放API:Spotify Web API

这个API包含了众多的歌曲,并且可以在线免费播放

使用步骤:

  1. 注册并创建Spotify开发者账号
    访问 Spotify for Developers 并登录或注册一个Spotify账号。
  2. 创建Spotify应用程序
    • 登录后,点击"Create an App"按钮,填写应用的名称和描述,点击"Create"创建应用。
    • 创建应用后,你会获得 Client ID 和 Client Secret。这是你访问Spotify API的凭证。
  3. 获取访问令牌
    Spotify API需要OAuth认证来获取访问令牌。访问令牌有两种方式获取:
    • 客户端凭据流:适用于不需要用户数据的场景。
    • 授权码流:适用于需要访问用户数据的场景。
  4. 发送API请求

使用Spotify Web API相较于本项目可能需要进行一些前置设置的操作,但后续的操作与本项目相差不大。只要你掌握了基础知识,就能够轻松地适应这个API的使用。

相关推荐
醉颜凉几秒前
银河麒麟桌面操作系统修改默认Shell为Bash
运维·服务器·开发语言·bash·kylin·国产化·银河麒麟操作系统
NiNg_1_2344 分钟前
npm、yarn、pnpm之间的区别
前端·npm·node.js
秋殇与星河6 分钟前
CSS总结
前端·css
NiNg_1_2346 分钟前
Vue3 Pinia持久化存储
开发语言·javascript·ecmascript
带带老表学爬虫15 分钟前
java数据类型转换和注释
java·开发语言
qianbo_insist17 分钟前
simple c++ 无锁队列
开发语言·c++
BigYe程普28 分钟前
我开发了一个出海全栈SaaS工具,还写了一套全栈开发教程
开发语言·前端·chrome·chatgpt·reactjs·个人开发
彭于晏68930 分钟前
Android广播
android·java·开发语言
余生H1 小时前
前端的全栈混合之路Meteor篇:关于前后端分离及与各框架的对比
前端·javascript·node.js·全栈
程序员-珍1 小时前
使用openapi生成前端请求文件报错 ‘Token “Integer“ does not exist.‘
java·前端·spring boot·后端·restful·个人开发