When I use the stream command on my bot, it streams about 1min 30s of audio before cutting off and not playing audio, and it doesn't give error messages at the start or when cutting off. When I use the download and play command instead, it plays the whole song without errors or cutoffs.
Stream command:
async def play(ctx, *, search):
voiceChannel=ctx.message.author.voice.channel
await voiceChannel.connect()
voice = discord.utils.get(client.voice_clients, guild=ctx.guild)
query_string = urllib.parse.urlencode({
'search_query': search
})
htm_content = urllib.request.urlopen(
'http://www.youtube.com/results?' + query_string
)
search_results = re.findall(r"watch\?v=(\S{11})", htm_content.read().decode())
url = 'http://www.youtube.com/watch?v=' + search_results[0]
ydl_opts = {
'format': 'bestaudio/best',
'postprocessors': [{
'key': 'FFmpegExtractAudio',
'preferredcodec': 'mp3',
'preferredquality': '192',
}],
}
with youtube_dl.YoutubeDL(ydl_opts) as ydl:
song_info = ydl.extract_info(url, download=False)
voice.play(discord.FFmpegPCMAudio(song_info["formats"][0]["url"]))
Download command:
async def download(ctx, *, search):
song_there = os.path.isfile("song.mp3")
try:
if song_there:
os.remove("song.mp3")
except PermissionError:
await ctx.send("Wait for the current playing music to end or use the 'stop' command")
return
voiceChannel=ctx.message.author.voice.channel
await voiceChannel.connect()
voice = discord.utils.get(client.voice_clients, guild=ctx.guild)
query_string = urllib.parse.urlencode({
'search_query': search
})
htm_content = urllib.request.urlopen(
'http://www.youtube.com/results?' + query_string
)
search_results = re.findall(r"watch\?v=(\S{11})", htm_content.read().decode())
ydl_opts = {
'format': 'bestaudio/best',
'postprocessors': [{
'key': 'FFmpegExtractAudio',
'preferredcodec': 'mp3',
'preferredquality': '192',
}],
}
with youtube_dl.YoutubeDL(ydl_opts) as ydl:
ydl.download(['http://www.youtube.com/watch?v=' + search_results[0]])
for file in os.listdir("./"):
if file.endswith(".mp3"):
os.rename(file, "song.mp3")
voice.play(discord.FFmpegPCMAudio("song.mp3"))
Alright, so I found the answer here on stackoverflow dot com at When playing audio, the last part is cut off. How can this be fixed? (discord.py). I quote, "This is a known issue when you try to make a bot which doesn't download the song it's playing. It is explained here : https://support.discord.com/hc/en-us/articles/360035010351--Known-Issue-Music-Bots-Not-Playing-Music-From-Certain-Sources"
Turns out you just needed to give FFMPEG options to reconnect and play the song as shown in the code below
FFMPEG_OPTIONS = {'before_options': '-reconnect 1 -reconnect_streamed 1 -reconnect_delay_max 5', 'options': '-vn'}
#client.command(
name='play',
description='Streams audio from Youtube. Syntax: w!play [keyword(s)].')
async def play(ctx, *, search):
voiceChannel=ctx.message.author.voice.channel
await voiceChannel.connect()
voice = discord.utils.get(client.voice_clients, guild=ctx.guild)
query_string = urllib.parse.urlencode({
'search_query': search
})
htm_content = urllib.request.urlopen(
'http://www.youtube.com/results?' + query_string
)
search_results = re.findall(r"watch\?v=(\S{11})", htm_content.read().decode())
url = 'http://www.youtube.com/watch?v=' + search_results[0]
ydl_opts = {
'format': 'bestaudio/best',
'postprocessors': [{
'key': 'FFmpegExtractAudio',
'preferredcodec': 'mp3',
'preferredquality': '192',
}],
}
with youtube_dl.YoutubeDL(ydl_opts) as ydl:
song_info = ydl.extract_info(url, download=False)
voice.play(discord.FFmpegPCMAudio(song_info["formats"][0]["url"], **FFMPEG_OPTIONS))
For whatever reason, some
Related
I making discord bot and i am trying to move from youtube_dl to yt_dlp to get +18 videos from youtube, I am getting error Output file #0 does not contain any stream.
self.YTDL_OPTIONS = {'format': 'bestaudio', 'nonplaylist': 'True', 'youtube_include_dash_manifest': False}
self.FFMPEG_OPTIONS = {
'before_options': '-reconnect 1 -reconnect_streamed 1 -reconnect_delay_max 5',
'options': '-vn'
}
with YoutubeDL(self.YTDL_OPTIONS) as ydl:
try:
info = ydl.extract_info(url, download=False)
except:
return False
return {
'link': 'https://www.youtube.com/watch?v=' + url,
'thumbnail': 'https://i.ytimg.com/vi/' + url + '/hqdefault.jpg?sqp=-oaymwEcCOADEI4CSFXyq4qpAw4IARUAAIhCGAFwAcABBg==&rs=AOn4CLD5uL4xKN-IUfez6KIW_j5y70mlig',
'source': info['formats'][0]['url'],
'title': info['title']
}
self.vc[id].play(discord.FFmpegPCMAudio(
song['source'], **self.FFMPEG_OPTIONS), after=lambda e: self.play_next(interaction))
This config works with youtube_dl, but not with yt_dlp. Any ideas what i should change?
Can anyone help me with this?
For the button, it shows: IndentationError: unexpected indent
#bot.command()
async def button(ctx):
await ctx.send("hello",components = [
[Button(label="hi",style="3",custom_id="button1"), Button(label="bye",style="4",custom_id="button2")]
])
interaction = await bot.wait_for("button_click", check = lambda i:i.custon_id == "button1" )
await interaction.send(content = "BUtton Clicked", ephemeral=True)
For the select, it only shows urmom...
#bot.command()
async def select(ctx):
await ctx.send("Select", components= [
Select(
placeholder = "Select Something",
options = [
SelectOption(label="A",value="A"),
SelectOption(label="B",value="B")
])
])
while True:
try:
select_interaction = await bot.wait_for("select_option")
await select_interaction.send(content = f"{select_interaction.values[0]} selected", emphemral=False)
except:
await ctx.send("urmom")
I'm trying to build a service on a linux server to record video a web browser with its sound.
The first step I did with the source code below (using xvfb, puppeteer and ffmpeg) to record successfully.
However when I do a recording with different processes at a same time (different websites) the audio gets mixed up between the processes.
I know this is happening because I used the same default audio output for all processes.
The question is: how can I record the browser with sound that doesn't get mixed up between different processes?
My sample code below:
var Xvfb = require('xvfb');
var puppeteer = require('puppeteer');
const { spawn, spawnSync } = require('child_process');
async function record() {
var xvfb = new Xvfb({
displayNum: 99,
reuse: false,
xvfb_args: [
"-screen", "0", "1920x1080x24",
"-ac",
"-nolisten", "tcp",
"-dpi", "96",
"+extension", "RANDR"
]
});
xvfb.startSync();
var browser = await puppeteer.launch({
headless: false,
defaultViewport: null,
ignoreDefaultArgs: [
"--mute-audio",
"--enable-automation"
],
args: [
"--use-fake-ui-for-media-stream",
"--window-size=1920,1080",
"--start-fullscreen"
]
});
const page = await browser.newPage();
var url = "http://www.noiseaddicts.com/free-samples-mp3/?id=2544";
await page.goto(url);
await page.click('span.map_play');
var time = new Date().getTime();
var options = [
"-video_size", "1920x1080",
"-framerate", "30",
"-f", "x11grab",
"-draw_mouse", "0",
"-i", ":99",
"-f", "pulse",
"-ac", "2",
"-i", "1",
"./output" + time + ".mkv"
];
var cmd = 'ffmpeg';
var proc = spawn(cmd, options);
proc.stdout.on('data', function (data) {
console.log(data);
});
proc.stderr.setEncoding("utf8")
proc.stderr.on('data', function (data) {
console.log(data);
});
proc.on('close', async function () {
console.log('finished');
xvfb.stopSync();
});
}
record();
use puppeteer-stream. and run examples/ffmpeg.js with xfvb-run --auto-servernum node ffmpeg.js you will see the captured output.
I'm coding my first music bot for discord and successfully tested it on the localhost. After that, I moved it on Heroku and installed FFmpeg buildpack for it. But for some reason, it doesn't work.
Here is proof that I installed FFmpeg buildpack on Heroku: Screen
Here is my code (that works well on localhost):
youtube_dl.utils.bug_reports_message = lambda: ''
ytdl_format_options = {
'format': 'bestaudio/best',
'outtmpl': '%(extractor)s-%(id)s-%(title)s.%(ext)s',
'restrictfilenames': True,
'noplaylist': True,
'nocheckcertificate': True,
'ignoreerrors': False,
'logtostderr': False,
'quiet': True,
'no_warnings': True,
'default_search': 'auto',
'source_address': '0.0.0.0'
}
ffmpeg_options = {
'options': '-vn'
}
ytdl = youtube_dl.YoutubeDL(ytdl_format_options)
class YTDLSource(discord.PCMVolumeTransformer):
def __init__(self, source, *, data, volume=0.5):
super().__init__(source, volume)
self.data = data
self.title = data.get('title')
self.url = data.get('url')
#classmethod
async def from_url(cls, url, *, loop=None, stream=False):
loop = loop or asyncio.get_event_loop()
data = await loop.run_in_executor(None, lambda: ytdl.extract_info(url, download=not stream))
if 'entries' in data:
data = data['entries'][0]
filename = data['url'] if stream else ytdl.prepare_filename(data)
return cls(discord.FFmpegPCMAudio(filename, **ffmpeg_options), data=data)
#client.command()
async def join(ctx):
channel = ctx.message.author.voice.channel
if ctx.voice_client is not None:
return await ctx.voice_client.move_to(channel)
await channel.connect()
#client.command()
async def play(ctx, *, URL):
async with ctx.typing():
player = await YTDLSource.from_url(url)
ctx.voice_client.play(player, after=lambda e: print('Player error: %s' % e) if e else None)
await ctx.send('Now playing: {}'.format(player.title))
I'm using webdriverio and need to wait for an element to be in the viewport
So I tried
browser.waitUntil(async () => {
const b = await link.isDisplayedInViewport()
return b;
}, 5000, 'expected to be visible after 5s');
But somehow waitUntil wants a boolean not a Promise<boolean>
How can I fix this?
Update:
I use WebdriverIO in a NodeJs app as follows
const { remote } = require('webdriverio');
(async () => {
const browser = await remote({
logLevel: 'error',
path: '/',
capabilities: {
browserName: 'chrome'
}
});
await browser.url('https://example.com');
const link = await browser.$('.special-link');
const ok = await browser.waitUntil(async () => {
const b = await link.isDisplayedInViewport()
return b;
}, 5000, 'expected to be visible after 5s');
await link.click();
const title = await browser.getTitle();
console.log('Title was: ' + title);
await browser.deleteSession();
})().catch((e) => console.error(e));
source
In the options is don't see anything about with or without async/await. Furthermore I don't use a testing framework!
Sorry for the late answer. But if you are still looking for a solution, Please try this if you want to avoid aync/await
get link() { return browser.element('.special-link'); }
browser.waitUntil(() => this.link.isVisibleWithinViewport(), 20000, 'link not visible')
const elementWaitingToBeDisplayed = $("some element locators")
elementWaitingToBeDisplayed.waitForDisplayed(10000, false)
If you set the second argument of elementWaitingToBeDisplayed.waitForDisplayed to true it waits for the opposite.