ボットで「再生」コマンドを使用すると (現在、オーディオ ファイルへのパスを使用してローカルでのみ動作します)、ボットがメッセージを送信する
An exception occured during playback: System.ComponentModel.Win32Exception: The system cannot find the file specified
という問題がありました。コードと同様にオンラインで答えを見つけようとしましたが、役立つものは何も見つかりませんでした(質問を書いている時点で、私のコードはほとんどチュートリアルのコードで構成されており、少し変更しました)
メインコード:
using DiscordBot2.Commands;
using DSharpPlus;
using DSharpPlus.CommandsNext;
using DSharpPlus.EventArgs;
using Microsoft.Extensions.Logging;
using Newtonsoft.Json;
using System;
using System.Collections.Generic;
using System.IO;
using System.Text;
using System.Threading.Tasks;
using DSharpPlus.Interactivity;
using DSharpPlus.Interactivity.Extensions;
using DSharpPlus.VoiceNext;
namespace DiscordBot2
{
public class Bot
{
public DiscordClient Client { get; private set; }
public CommandsNextExtension Commands { get; private set; }
public VoiceNextExtension Voice { get; set; }
public async Task RunAsync()
{
var json = string.Empty;
using (var fs = File.OpenRead("config.json"))
using (var sr = new StreamReader(fs, new UTF8Encoding(false)))
json = await sr.ReadToEndAsync().ConfigureAwait(false);
var configJson = JsonConvert.DeserializeObject<ConfigJson>(json);
var config = new DiscordConfiguration
{
Token = configJson.Token,
TokenType = TokenType.Bot,
AutoReconnect = true,
MinimumLogLevel = LogLevel.Debug,
};
Client = new DiscordClient(config);
Client.Ready += OnClientReady;
Client.UseInteractivity(new InteractivityConfiguration
{
Timeout = TimeSpan.FromMinutes(5)
});
var commandsConfig = new CommandsNextConfiguration
{
StringPrefixes = new string[] { configJson.Prefix },
EnableDms = false,
EnableMentionPrefix = true,
DmHelp = false
};
Commands = Client.UseCommandsNext(commandsConfig);
Commands.RegisterCommands<FunCommands>();
Commands.RegisterCommands<RoleCommands>();
Commands.RegisterCommands<ModerationCommands>();
Commands.RegisterCommands<MusicCommands>();
Voice = Client.UseVoiceNext();
await Client.ConnectAsync();
await Task.Delay(-1);
}
private Task OnClientReady(object sender, ReadyEventArgs e)
{
return Task.CompletedTask;
}
}
}
音楽コマンドを含むコード:
using DSharpPlus.CommandsNext;
using DSharpPlus.CommandsNext.Attributes;
using DSharpPlus.Entities;
using DSharpPlus.EventArgs;
using DSharpPlus.Interactivity;
using DSharpPlus.Interactivity.Extensions;
using DSharpPlus.VoiceNext;
using Microsoft.Extensions.Logging;
using Newtonsoft.Json;
using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.IO;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace DiscordBot2.Commands
{
class MusicCommands : BaseCommandModule
{
[Command("join")]
[ Description("Joins a voice channel.")]
public async Task Join(CommandContext ctx, DiscordChannel chn = null)
{
// check whether VNext is enabled
var vnext = ctx.Client.GetVoiceNext();
if (vnext == null)
{
// not enabled
await ctx.RespondAsync("VNext is not enabled or configured.");
return;
}
// check whether we aren't already connected
var vnc = vnext.GetConnection(ctx.Guild);
if (vnc != null)
{
// already connected
await ctx.RespondAsync("Already connected in this guild.");
return;
}
// get member's voice state
var vstat = ctx.Member?.VoiceState;
if (vstat?.Channel == null && chn == null)
{
// they did not specify a channel and are not in one
await ctx.RespondAsync("You are not in a voice channel.");
return;
}
// channel not specified, use user's
if (chn == null)
chn = vstat.Channel;
// connect
vnc = await vnext.ConnectAsync(chn);
await ctx.RespondAsync($"Connected to `{chn.Name}`");
}
[Command("leave")]
[ Description("Leaves a voice channel.")]
public async Task Leave(CommandContext ctx)
{
// check whether VNext is enabled
var vnext = ctx.Client.GetVoiceNext();
if (vnext == null)
{
// not enabled
await ctx.RespondAsync("VNext is not enabled or configured.");
return;
}
// check whether we are connected
var vnc = vnext.GetConnection(ctx.Guild);
if (vnc == null)
{
// not connected
await ctx.RespondAsync("Not connected in this guild.");
return;
}
// disconnect
vnc.Disconnect();
await ctx.RespondAsync("Disconnected");
}
[Command("play")]
[ Description("Plays an audio file.")]
public async Task Play(CommandContext ctx,
[RemainingText, Description("Full path to the file to play.")] string filename)
{
// check whether VNext is enabled
var vnext = ctx.Client.GetVoiceNext();
if (vnext == null)
{
// not enabled
await ctx.RespondAsync("VNext is not enabled or configured.");
return;
}
// check whether we aren't already connected
var vnc = vnext.GetConnection(ctx.Guild);
if (vnc == null)
{
// already connected
await ctx.RespondAsync("Not connected in this guild.");
return;
}
// check if file exists
if (!File.Exists(filename))
{
// file does not exist
await ctx.RespondAsync($"File `{filename}` does not exist.");
return;
}
// wait for current playback to finish
while (vnc.IsPlaying)
await vnc.WaitForPlaybackFinishAsync();
// play
Exception exc = null;
await ctx.Message.RespondAsync($"Playing `{filename}`");
try
{
await vnc.SendSpeakingAsync(true);
var psi = new ProcessStartInfo
{
FileName = "ffmpeg.exe",
Arguments = $@"-i ""{filename}"" -ac 2 -f s16le -ar 48000 pipe:1 -loglevel quiet",
RedirectStandardOutput = true,
UseShellExecute = false
};
var ffmpeg = Process.Start(psi);
var ffout = ffmpeg.StandardOutput.BaseStream;
var txStream = vnc.GetTransmitSink();
await ffout.CopyToAsync(txStream);
await txStream.FlushAsync();
await vnc.WaitForPlaybackFinishAsync();
}
catch (Exception ex) { exc = ex; }
finally
{
await vnc.SendSpeakingAsync(false);
await ctx.Message.RespondAsync($"Finished playing `{filename}`");
}
if (exc != null)
await ctx.RespondAsync($"An exception occured during playback: `{exc.GetType()}: {exc.Message}`");
}
}
}
(エラー メッセージを表示する行は、MusicCommands スクリプトの一番下にあります)
if (exc != null)
await ctx.RespondAsync($"An exception occured during playback: `{exc.GetType()}: {exc.Message}`");