Пример #1
0
        private async Task WriteStreamToVoiceChannel(AudioClient audioClient, AudioOutStream discord, MemoryStream memoryStream)
        {
            try
            {
                await discord.WriteAsync(memoryStream.ToArray(), 0, (int)memoryStream.Length);
            }
            finally
            {
                await memoryStream.DisposeAsync();

                await discord.FlushAsync();

                await discord.DisposeAsync();

                // Clear current stream
                audioClient.CurrentStream = null;

                // Play next
                AudioOnlyStreamInfo nextSong = audioClient.GetNextSong();
                if (nextSong != null)
                {
                    this.StartStream(youtube, audioClient, nextSong, null);
                }
            }
        }
Пример #2
0
        private string GetFileNameWithExtension(AudioOnlyStreamInfo streamInfo)
        {
            string extension = streamInfo.IsOpus() && ExtractOpus ? "opus" : streamInfo.Container.Name;

            string fileName = GetSafeFileName(VideoMetaData?.Title ?? HttpUtility.ParseQueryString(new Uri(YouTubeUrl).Query)["v"] ?? Path.GetRandomFileName());

            return($"{fileName}.{extension}");
        }
Пример #3
0
 public void SkipCurrentSong(IMessage message, ulong guildId)
 {
     if (this.connectedChannels.TryGetValue(guildId, out AudioClient audioClient))
     {
         AudioOnlyStreamInfo nextSong = audioClient.GetNextSong();
         if (nextSong != null)
         {
             this.StartStream(youtube, audioClient, nextSong, message);
         }
         else
         {
             message.DeleteAsync();
         }
     }
 }
Пример #4
0
        private string GetVideoUrl(string videoId, uint channelBitrate)
        {
            var manifest = Program.YouTubeClient.Videos.Streams.GetManifestAsync(videoId).Result;

            AudioOnlyStreamInfo bestStream = null;

            foreach (var stream in manifest.GetAudioOnlyStreams().OrderBy(s => s.Bitrate))
            {
                if (bestStream == null || stream.Bitrate > bestStream.Bitrate)
                {
                    bestStream = stream;

                    if (stream.Bitrate.BitsPerSecond > channelBitrate)
                    {
                        break;
                    }
                }
            }

            return(bestStream.Url);
        }
Пример #5
0
        public async Task Play(ICoreHandler handler, Message message, string param)
        {
            Video vid = (await client.Search.GetVideosAsync(param)).FirstOrDefault();

            if (vid != null)
            {
                if (vid.Duration <= TimeSpan.FromMinutes(10))
                {
                    StreamManifest streamManifest = await client.Videos.Streams.GetManifestAsync(vid.Id);

                    AudioOnlyStreamInfo audio = streamManifest.GetAudioOnly().FirstOrDefault();
                    if (audio != null)
                    {
                        MemoryStream stream = new MemoryStream();
                        await client.Videos.Streams.CopyToAsync(audio, stream);

                        Debug(audio.AudioCodec);
                        unsafe {
                            AVPacket *pkt   = ffmpeg.av_packet_alloc();
                            AVCodec * codec = ffmpeg.avcodec_find_decoder_by_name(audio.AudioCodec);
                            if (codec == null)
                            {
                                Error($"Codec {audio.AudioCodec} not found.");
                                return;
                            }
                            AVCodecParserContext *parser = ffmpeg.av_parser_init((int)codec->id);
                            if (parser == null)
                            {
                                Error("Could not allocate audio codec context.");
                                return;
                            }
                            AVCodecContext *context = ffmpeg.avcodec_alloc_context3(codec);
                            if (context == null)
                            {
                                Error("Could not allocate audio codec context.");
                                return;
                            }
                            if (ffmpeg.avcodec_open2(context, codec, null) < 0)
                            {
                                Error("Could not open audio codec context.");
                                return;
                            }
                            AVFrame *decoded_frame = null;
                            while (stream.Length - stream.Position > 0)
                            {
                                if (decoded_frame == null)
                                {
                                    decoded_frame = ffmpeg.av_frame_alloc();
                                }
                                byte[] buffer = new byte[pkt->size];
                                stream.Read(buffer, 0, buffer.Length);
                                IntPtr unmanagedPointer = Marshal.AllocHGlobal(buffer.Length);
                                Marshal.Copy(buffer, 0, unmanagedPointer, buffer.Length);
                                ffmpeg.av_parser_parse2(parser, context, &pkt->data, &pkt->size, (byte *)unmanagedPointer, buffer.Length, ffmpeg.AV_NOPTS_VALUE, ffmpeg.AV_NOPTS_VALUE, 0);
                                int ret = ffmpeg.avcodec_send_packet(context, pkt);
                                while (ret > 0)
                                {
                                    ret = ffmpeg.avcodec_receive_frame(context, decoded_frame);
                                    int data_size = ffmpeg.av_get_bytes_per_sample(context->sample_fmt);
                                    int current   = 0;
                                    for (int i = 0; i < decoded_frame->nb_samples; i++)
                                    {
                                        for (uint ch = 0; ch < context->channels; ch++)
                                        {
                                            Marshal.Copy((IntPtr)decoded_frame->data[ch] + (data_size * i), buffer, current, data_size);
                                            current += data_size;
                                        }
                                    }
                                    message.TransferSound(buffer);
                                }
                                Marshal.FreeHGlobal(unmanagedPointer);
                            }
                        }
                    }
                }
                else
                {
                    Warn("Video too long.");
                }
            }
            else
            {
                Warn("No video by that term.");
            }

            /*DiscordGuildTextChannel Channel = client.GetChannel(e.Message.ChannelId).Result as DiscordGuildTextChannel;
             * Snowflake GuildId = Channel.GuildId;
             * DiscordGuild Guild = await client.GetGuild(GuildId);
             * Snowflake ChannelId = e.Message.ChannelId;
             * DiscordVoiceState voiceState = e.Shard.Cache.GetVoiceState(GuildId, e.Message.Author.Id);
             * if (voiceState == null) {
             *  return;
             * } else {
             *  if (!SharedObjectStorage.VoiceModuleObjects.Keys.Contains(voiceState.ChannelId.Value)) {
             *      VoiceModule music = new VoiceModule(e.Shard, voiceState.ChannelId.Value);
             *      SharedObjectStorage.VoiceModuleObjects.Add(voiceState.ChannelId.Value, music);
             *      if (Tempnamelist.Count <= 2) {
             *          Tempnamelist.Add($"Temp{i++}");
             *      }
             *      string filename = Tempnamelist[0];
             *      Tempnamelist.RemoveAt(0);
             *      voice = new YoutubeVoiceProvider();
             *      voice.DoQuery(query);
             *      client.CreateMessage(e.Message.ChannelId, "" + String.Join("\n", voice.Result));
             *      this.GuildId = ((await client.GetChannel(e.Message.ChannelId)) as DiscordGuildTextChannel).GuildId;
             *      UserId = e.Message.Author.Id;
             *      e.Shard.Gateway.OnMessageCreated += Gateway_OnMessageCreated1;
             *      stopsignal.WaitOne();
             *      e.Shard.Gateway.OnMessageCreated -= Gateway_OnMessageCreated1;
             *      voice.DownloadToFileByQuery($"Temp/{filename}").Wait();
             *      if (new FileInfo($"Temp/{filename}").Length <= 100) { return; }
             *      client.CreateMessage(e.Message.ChannelId, "Playing: " + voice.CurrentSelection);
             *      Converter c = new FFmpegConverter();
             *      c.TempfileClosed += TempfileClosed;
             *      music.Transfer(new FileInfo($"Temp/{filename}"), c, playCancellationTokenSource);
             *  }
             * }*/
        }
 public static string GetTitle(this AudioOnlyStreamInfo info)
 {
     return($"{info.Container.Name} - {info.AudioCodec} - {info.Bitrate} - ({info.Size})");
 }
 public static bool IsOpus(this AudioOnlyStreamInfo info)
 {
     return(info.AudioCodec == AudioCodecOpus);
 }
 public DownloadOption(string format, AudioOnlyStreamInfo audioOnlyStreamInfo, VideoOnlyStreamInfo videoOnlyStreamInfo)
     : this(format, videoOnlyStreamInfo.VideoQualityLabel, new IStreamInfo[] { audioOnlyStreamInfo, videoOnlyStreamInfo })
 {
 }
 public DownloadOption(string format, AudioOnlyStreamInfo audioOnlyStreamInfo)
     : this(format, "Audio", new[] { audioOnlyStreamInfo })
 {
 }
Пример #10
0
    private async ValueTask PopulateStreamInfosAsync(
        ICollection <IStreamInfo> streamInfos,
        IEnumerable <IStreamInfoExtractor> streamInfoExtractors,
        CancellationToken cancellationToken = default)
    {
        foreach (var streamInfoExtractor in streamInfoExtractors)
        {
            var itag =
                streamInfoExtractor.TryGetItag() ??
                throw new YoutubeExplodeException("Could not extract stream itag.");

            var url =
                streamInfoExtractor.TryGetUrl() ??
                throw new YoutubeExplodeException("Could not extract stream URL.");

            // Get content length
            var contentLength =
                streamInfoExtractor.TryGetContentLength() ??
                await _http.TryGetContentLengthAsync(url, false, cancellationToken) ??
                0;

            if (contentLength <= 0)
            {
                continue; // broken stream URL?
            }
            var fileSize = new FileSize(contentLength);

            var container =
                streamInfoExtractor.TryGetContainer()?.Pipe(s => new Container(s)) ??
                throw new YoutubeExplodeException("Could not extract stream container.");

            var bitrate =
                streamInfoExtractor.TryGetBitrate()?.Pipe(s => new Bitrate(s)) ??
                throw new YoutubeExplodeException("Could not extract stream bitrate.");

            var audioCodec = streamInfoExtractor.TryGetAudioCodec();
            var videoCodec = streamInfoExtractor.TryGetVideoCodec();

            // Muxed or video-only stream
            if (!string.IsNullOrWhiteSpace(videoCodec))
            {
                var framerate = streamInfoExtractor.TryGetFramerate() ?? 24;

                var videoQualityLabel = streamInfoExtractor.TryGetVideoQualityLabel();

                var videoQuality = !string.IsNullOrWhiteSpace(videoQualityLabel)
                    ? VideoQuality.FromLabel(videoQualityLabel, framerate)
                    : VideoQuality.FromItag(itag, framerate);

                var videoWidth  = streamInfoExtractor.TryGetVideoWidth();
                var videoHeight = streamInfoExtractor.TryGetVideoHeight();

                var videoResolution = videoWidth is not null && videoHeight is not null
                    ? new Resolution(videoWidth.Value, videoHeight.Value)
                    : videoQuality.GetDefaultVideoResolution();

                // Muxed
                if (!string.IsNullOrWhiteSpace(audioCodec))
                {
                    var streamInfo = new MuxedStreamInfo(
                        url,
                        container,
                        fileSize,
                        bitrate,
                        audioCodec,
                        videoCodec,
                        videoQuality,
                        videoResolution
                        );

                    streamInfos.Add(streamInfo);
                }
                // Video-only
                else
                {
                    var streamInfo = new VideoOnlyStreamInfo(
                        url,
                        container,
                        fileSize,
                        bitrate,
                        videoCodec,
                        videoQuality,
                        videoResolution
                        );

                    streamInfos.Add(streamInfo);
                }
            }
            // Audio-only
            else if (!string.IsNullOrWhiteSpace(audioCodec))
            {
                var streamInfo = new AudioOnlyStreamInfo(
                    url,
                    container,
                    fileSize,
                    bitrate,
                    audioCodec
                    );

                streamInfos.Add(streamInfo);
            }
            else
            {
                Debug.Fail("Stream doesn't contain neither audio nor video codec information.");
            }
        }
    }
Пример #11
0
        private async void StartStream(YoutubeClient youtube, AudioClient audioClient, AudioOnlyStreamInfo streamInfo, IMessage?message)
        {
            Stream ytStream = await youtube.Videos.Streams.GetAsync(streamInfo);

            // Convert yt stream
            MemoryStream memoryStream = new MemoryStream();
            await Cli.Wrap("ffmpeg")
            .WithArguments(" -hide_banner -loglevel panic -i pipe:0 -ac 2 -f s16le -ar 48000 pipe:1")
            .WithStandardInputPipe(PipeSource.FromStream(ytStream))
            .WithStandardOutputPipe(PipeTarget.ToStream(memoryStream))
            .ExecuteAsync();

            // Clear stream before beginning
            if (audioClient.CurrentStream != null)
            {
                audioClient.CurrentStream.Dispose();
                audioClient.CurrentStream = null;
            }

            AudioOutStream discord = audioClient.Client.CreatePCMStream(AudioApplication.Mixed);

            audioClient.CurrentStream = discord;

            // Delete calling command
            if (message != null)
            {
                await message.DeleteAsync();
            }

            // Start playing music
            await this.WriteStreamToVoiceChannel(audioClient, discord, memoryStream);
        }
Пример #12
0
        public async Task SendYoutubeAudioAsync(IMessage message, IGuildUser user, string query)
        {
            // Check that we have a query
            if (string.IsNullOrWhiteSpace(query))
            {
                return;
            }

            if (this.connectedChannels.TryGetValue(user.GuildId, out AudioClient audioClient))
            {
                VideoInfo videoInfo = new VideoInfo(user.GetName());

                // Try to parse the url given to return just the video id
                string id;
                if (query.Contains("v=") && query.Length >= 3)
                {
                    if (query.Contains("&"))
                    {
                        id = Regex.Match(query, "v=(.*?)&").ToString();
                        id = id.Substring(2, id.Length - 3);
                    }
                    else
                    {
                        id = Regex.Match(query, "v=(.*?)$").ToString();
                        id = id.Substring(2, id.Length - 2);
                    }

                    YoutubeExplode.Videos.Video video = await youtube.Videos.GetAsync(id);

                    videoInfo.Title     = video.Title;
                    videoInfo.Duration  = video.Duration.ToString();
                    videoInfo.Thumbnail = video.Thumbnails.GetFirst().Url;
                }
                else
                {
                    // Get the stream from YT via search
                    IReadOnlyList <YoutubeExplode.Search.VideoSearchResult> searchResult = await youtube.Search.GetVideosAsync(query).CollectAsync(1);

                    YoutubeExplode.Search.VideoSearchResult result = searchResult.GetFirst();

                    videoInfo.Title     = result.Title;
                    videoInfo.Duration  = result.Duration.ToString();
                    videoInfo.Thumbnail = result.Thumbnails.GetFirst().Url;

                    id = result.Id;
                }

                // Get the stream from YT via video id
                StreamManifest streamManifest = await youtube.Videos.Streams.GetManifestAsync(id);

                AudioOnlyStreamInfo streamInfo = streamManifest.GetAudioOnlyStreams().GetFirst();

                videoInfo.Stream = streamInfo;

                // If song currently playing, add to playlist
                if (audioClient.CurrentStream != null)
                {
                    audioClient.PlayList.Add(videoInfo);

                    // Delete calling command
                    await message.DeleteAsync();
                }
                else
                {
                    // Play song
                    audioClient.CurrentSong = videoInfo;
                    this.StartStream(youtube, audioClient, streamInfo, message);
                }
            }
        }
        private static void SelectMediaStreamInfoSet(StreamManifest streamManifest, Settings settings, SettingDownload settingDownload, out AudioOnlyStreamInfo audioStreamInfo, out VideoOnlyStreamInfo videoStreamInfo)
        {
            //Todo make a better selection process
            //by largest container bitrate

            audioStreamInfo = streamManifest
                              .GetAudioOnly()
                              .Where(s => s.Container == Container.Mp4)
                              .OrderByDescending(s => s.Bitrate)
                              .First();

            videoStreamInfo = streamManifest
                              .GetVideoOnly()
                              .Where(s => s.Container == Container.Mp4)
                              .OrderByDescending(s => s.VideoQuality)
                              .ThenByDescending(s => s.Framerate)
                              .First();

            if (settingDownload.MediaType == MediaType.Audio)
            {
                audioStreamInfo = streamManifest
                                  .GetAudioOnly()
                                  .OrderByDescending(s => s.Bitrate)
                                  .First();
            }

            if (settingDownload.MediaType == MediaType.Video)
            {
                videoStreamInfo = streamManifest
                                  .GetVideoOnly()
                                  .Where(s => s.Container == Container.Mp4)
                                  .OrderByDescending(s => s.VideoQuality)
                                  .ThenByDescending(s => s.Framerate)
                                  .First();
            }
        }