
Recherche avancée
Médias (1)
-
Revolution of Open-source and film making towards open film making
6 octobre 2011, par
Mis à jour : Juillet 2013
Langue : English
Type : Texte
Autres articles (52)
-
Mise à jour de la version 0.1 vers 0.2
24 juin 2013, parExplications des différents changements notables lors du passage de la version 0.1 de MediaSPIP à la version 0.3. Quelles sont les nouveautés
Au niveau des dépendances logicielles Utilisation des dernières versions de FFMpeg (>= v1.2.1) ; Installation des dépendances pour Smush ; Installation de MediaInfo et FFprobe pour la récupération des métadonnées ; On n’utilise plus ffmpeg2theora ; On n’installe plus flvtool2 au profit de flvtool++ ; On n’installe plus ffmpeg-php qui n’est plus maintenu au (...) -
Personnaliser en ajoutant son logo, sa bannière ou son image de fond
5 septembre 2013, parCertains thèmes prennent en compte trois éléments de personnalisation : l’ajout d’un logo ; l’ajout d’une bannière l’ajout d’une image de fond ;
-
Ecrire une actualité
21 juin 2013, parPrésentez les changements dans votre MédiaSPIP ou les actualités de vos projets sur votre MédiaSPIP grâce à la rubrique actualités.
Dans le thème par défaut spipeo de MédiaSPIP, les actualités sont affichées en bas de la page principale sous les éditoriaux.
Vous pouvez personnaliser le formulaire de création d’une actualité.
Formulaire de création d’une actualité Dans le cas d’un document de type actualité, les champs proposés par défaut sont : Date de publication ( personnaliser la date de publication ) (...)
Sur d’autres sites (6265)
-
"FFmpeg : Error not transitioning to the next song in Discord Bot's queue."
1er avril 2024, par nooberI have 3 modules, but I'm sure the error occurs within this module, and here is the entire code within that module :


import asyncio
import discord
from discord import FFmpegOpusAudio, Embed
import os

async def handle_help(message):
 embed = discord.Embed(
 title="Danh sách lệnh cho Bé Mèo",
 description="Dưới đây là các lệnh mà chủ nhân có thể bắt Bé Mèo phục vụ:",
 color=discord.Color.blue()
 )
 embed.add_field(name="!play", value="Phát một bài hát từ YouTube.", inline=False)
 embed.add_field(name="!pause", value="Tạm dừng bài hát đang phát.", inline=False)
 embed.add_field(name="!resume", value="Tiếp tục bài hát đang bị tạm dừng.", inline=False)
 embed.add_field(name="!skip", value="Chuyển đến bài hát tiếp theo trong danh sách chờ.", inline=False)
 embed.add_field(name="!stop", value="Dừng phát nhạc và cho phép Bé Mèo đi ngủ tiếp.", inline=False)
 # Thêm các lệnh khác theo cùng mẫu trên
 await message.channel.send(embed=embed)

class Song:
 def __init__(self, title, player):
 self.title = title # Lưu trữ tiêu đề bài hát ở đây
 self.player = player

# Thêm đối tượng Song vào hàng đợi
def add_song_to_queue(guild_id, queues, song):
 queues.setdefault(guild_id, []).append(song)

async def handle_list(message, queues):
 log_file_path = "C:\\Bot Music 2\\song_log.txt"
 if os.path.exists(log_file_path):
 with open(log_file_path, "r", encoding="utf-8") as f:
 song_list = f.readlines()

 if song_list:
 embed = discord.Embed(
 title="Danh sách bài hát",
 description="Danh sách các bài hát đã phát:",
 color=discord.Color.blue()
 )

 for i, song in enumerate(song_list, start=1):
 if i == 1:
 song = "- Đang phát: " + song.strip()
 embed.add_field(name=f"Bài hát {i}", value=song, inline=False)

 await message.channel.send(embed=embed)
 else:
 await message.channel.send("Hiện không có dữ liệu trong file log.")
 else:
 await message.channel.send("File log không tồn tại.")

async def handle_commands(message, client, queues, voice_clients, yt_dl_options, ytdl, ffmpeg_options=None, guild_id=None, data=None):
 # Nếu không có ffmpeg_options, sử dụng các thiết lập mặc định
 if ffmpeg_options is None:
 ffmpeg_options = {
 'before_options': '-reconnect 1 -reconnect_streamed 1 -reconnect_delay_max 5',
 'options': '-vn -filter:a "volume=0.25"'
 }
 
 # Khởi tạo voice_client
 if guild_id is None:
 guild_id = message.guild.id

 if guild_id in voice_clients:
 voice_client = voice_clients[guild_id]
 else:
 voice_client = None

 # Xử lý lệnh !play
 if message.content.startswith("!play"):
 try:
 # Kiểm tra xem người gửi tin nhắn có đang ở trong kênh voice không
 voice_channel = message.author.voice.channel
 # Kiểm tra xem bot có đang ở trong kênh voice của guild không
 if voice_client and voice_client.is_connected():
 await voice_client.move_to(voice_channel)
 else:
 voice_client = await voice_channel.connect()
 voice_clients[guild_id] = voice_client
 except Exception as e:
 print(e)

 try:
 query = ' '.join(message.content.split()[1:])
 if query.startswith('http'):
 url = query
 else:
 query = 'ytsearch:' + query
 loop = asyncio.get_event_loop()
 data = await loop.run_in_executor(None, lambda: ytdl.extract_info(query, download=False))
 if not data:
 raise ValueError("Không có dữ liệu trả về từ YouTube.")
 url = data['entries'][0]['url']

 player = FFmpegOpusAudio(url, **ffmpeg_options)
 # Lấy thông tin của bài hát mới đang được yêu cầu
 title = data['entries'][0]['title']
 duration = data['entries'][0]['duration']
 creator = data['entries'][0]['creator'] if 'creator' in data['entries'][0] else "Unknown"
 requester = message.author.nick if message.author.nick else message.author.name
 
 # Tạo embed để thông báo thông tin bài hát mới
 embed = discord.Embed(
 title="Thông tin bài hát mới",
 description=f"**Bài hát:** *{title}*\n**Thời lượng:** *{duration}*\n**Tác giả:** *{creator}*\n**Người yêu cầu:** *{requester}*",
 color=discord.Color.green()
 )
 await message.channel.send(embed=embed)
 
 # Sau khi lấy thông tin của bài hát diễn ra, gọi hàm log_song_title với title của bài hát
 # Ví dụ:
 title = data['entries'][0]['title']
 await log_song_title(title)

 # Thêm vào danh sách chờ nếu có bài hát đang phát
 if voice_client.is_playing():
 queues.setdefault(guild_id, []).append(player)
 else:
 voice_client.play(player)
 
 except Exception as e:
 print(e)
 
 if message.content.startswith("!link"):
 try:
 voice_client = await message.author.voice.channel.connect()
 voice_clients[voice_client.guild.id] = voice_client
 except Exception as e:
 print(e)

 try:
 url = message.content.split()[1]

 loop = asyncio.get_event_loop()
 data = await loop.run_in_executor(None, lambda: ytdl.extract_info(url, download=False))

 song = data['url']
 player = discord.FFmpegOpusAudio(song, **ffmpeg_options)

 voice_clients[message.guild.id].play(player)
 except Exception as e:
 print(e)

 # Xử lý lệnh !queue
 elif message.content.startswith("!queue"):
 queue = queues.get(guild_id, [])
 if queue:
 await message.channel.send("Danh sách chờ:")
 for index, item in enumerate(queue, 1):
 await message.channel.send(f"{index}. {item.title}")
 else:
 await message.channel.send("Không có bài hát nào trong danh sách chờ.")

 # Xử lý lệnh !skip
 elif message.content.startswith("!skip"):
 try:
 if voice_client and voice_client.is_playing():
 voice_client.stop()
 await play_next_song(guild_id, queues, voice_client, skip=True)
 await remove_first_line_from_log()
 except Exception as e:
 print(e)

 # Xử lý các lệnh như !pause, !resume, !stop
 elif message.content.startswith("!pause"):
 try:
 if voice_client and voice_client.is_playing():
 voice_client.pause()
 except Exception as e:
 print(e)

 elif message.content.startswith("!resume"):
 try:
 if voice_client and not voice_client.is_playing():
 voice_client.resume()
 except Exception as e:
 print(e)

 elif message.content.startswith("!stop"):
 try:
 if voice_client:
 voice_client.stop()
 await voice_client.disconnect()
 del voice_clients[guild_id] # Xóa voice_client sau khi dừng
 except Exception as e:
 print(e)

async def log_song_title(title):
 log_file_path = "C:\\Bot Music 2\\song_log.txt"
 try:
 # Kiểm tra xem tệp tin log đã tồn tại chưa
 if not os.path.exists(log_file_path):
 # Nếu chưa tồn tại, tạo tệp tin mới và ghi title vào tệp tin đó
 with open(log_file_path, 'w', encoding='utf-8') as file:
 file.write(title + '\n')
 else:
 # Nếu tệp tin log đã tồn tại, mở tệp tin và chèn title vào cuối tệp tin
 with open(log_file_path, 'a', encoding='utf-8') as file:
 file.write(title + '\n')
 except Exception as e:
 print(f"Error logging song title: {e}")

async def remove_first_line_from_log():
 log_file_path = "C:\\Bot Music 2\\song_log.txt"
 try:
 with open(log_file_path, "r", encoding="utf-8") as f:
 lines = f.readlines()
 # Xóa dòng đầu tiên trong list lines
 lines = lines[1:]
 with open(log_file_path, "w", encoding="utf-8") as f:
 for line in lines:
 f.write(line)
 except Exception as e:
 print(f"Error removing first line from log: {e}")
 
async def clear_log_file():
 log_file_path = "C:\\Bot Music 2\\song_log.txt"
 try:
 with open(log_file_path, "w", encoding="utf-8") as f:
 f.truncate(0)
 except Exception as e:
 print(f"Error clearing log file: {e}")


async def play_next_song(guild_id, queues, voice_client, skip=False):
 queue = queues.get(guild_id, [])
 if queue:
 player = queue.pop(0)
 voice_client.play(player, after=lambda e: asyncio.run_coroutine_threadsafe(play_next_song(guild_id, queues, voice_client, skip=False), voice_client.loop))
 if skip:
 return
 else:
 await remove_first_line_from_log() # Xóa dòng đầu tiên trong file log
 elif skip:
 await remove_first_line_from_log() # Xóa dòng đầu tiên trong file log
 await voice_client.disconnect()
 del voice_client[guild_id] # Xóa voice_client sau khi dừng
 else:
 await clear_log_file() # Xóa dòng đầu tiên trong file log
 await voice_client.disconnect()
 del voice_client[guild_id] # Xóa voice_client sau khi dừng



I have tried asking ChatGPT, Gemini, or Bing, and they always lead me into a loop of errors that cannot be resolved. This error only occurs when the song naturally finishes playing due to its duration. If the song is playing and I use the command !skip, the next song in the queue will play and function normally. I noticed that it seems like if a song ends naturally, the song queue is also cleared immediately. I hope someone can help me with this


-
Anomalie #4562 : Suite #4468 : Unification des CSS pour les boutons et les icônes
10 février 2021, par RastaPopoulos ♥Je vois pas trop où tu veux en venir. Si tu peux ajouter une classe "bouton_supprimer" dans ton HTML ça veut dire que tu peux aussi ajouter une balise #ICONEsupprimer, t’as bien la main dessus. Le 1er paramètre a exactement le même sens que la classe, et il n’est pas amené à changer au fil du temps. Les icônes derrière, peut-être, mais pas le paramètre de la balise.
Bah non, aucun rapport : une classe CSS, si on parle bien d’une classe qui n’est pas "icone_XXX", mais bien des classes de variante pour dire "ceci est un bouton de suppression", "ceci est un bouton d’édition d’un contenu", "ceci est un bouton de sauvegarde/d’enregistrement"… tout ça ce sont des classes qui donnent juste un sens à ce bouton, sans du tout préjuger de comment on veut le styler.
Alors que #ICONEtruc ça signifie uniquement : je veux insérer l’icône de ce nom.
En ce moment tous les gros acteurs se lancent dans le HTML non sémantiques, justement parce que désormais 90% des apps sont générées à base de morceaux autonomes (react etc) qui mélangent contenus et choix graphiques. D’ailleurs même avant les "css utilitaires", tous les gros frameworks poussaient aussi à ça, en obligeant à mettre des "col-4" etc dans le HTML, ce qui inscrit en dur le layout sans pouvoir le changer dans un thème. Je ne trouve pas que ce soit forcément un exemple à suivre. Mon impression est qu’on s’éloigne de plus en plus de la conception de base de la séparation HTML/CSS. Par exemple si on décide ergonomiquement que dans l’admin "tous les boutons pour le sens XXX et YYY doivent avoir leur icône" et puis plus tard à l’utilisation on s’aperçoit que c’est trop lourd et on décide comme bonne pratique "non en fait seulement les boutons pour le sens XXX doivent avoir un picto, mais pas YYY" : alors il faudra aller les retirer partout où on ne les veut plus à la fois core mais tous les plugins. Alors que c’est débile, c’est juste un choix graphique et ergonomique à un instant T. Alors ça dépend des utilisations, parfois c’est logique par rapport à la conception de l’appli (react etc, et encore, on pourrait arguer que justement elles sont parfois mal conçues).
Le seul problème que je vois c’est que ça peut se retrouver dans des formulaires ou des squelettes utilisés à la fois dans le public et le privé.
Dans le privé on veut utiliser forcément tel jeu d’icônes, dans le public ça doit pouvoir être surchargeable.Au moins pour tous les formulaires, il faut d’après moi considérer qu’ils ne doivent pas être propre à l’admin de SPIP. Cette admin les utilise, c’est une interface par défaut, fournie pour gérer ses contenus. Mais on doit pouvoir les utiliser facilement n’importe où.
Et c’est un bon exemple de la séparation : ajouter tel picto, c’est un choix de décoration propre à l’admin, parce que dans ce contexte là on veut ajouter un picto à tel endroit. Mais ailleurs, dans le site, etc, peut-être qu’on veut styler autrement. Pas juste changer l’icône (ce qui doit déjà être possible aussi), mais c’est d’autres choix graphiques. C’est bien pour ça que le HTML doit rester neutre et sémantique normalement.
-
Anomalie #4623 : Styles des fieldset dans l’espace privé
17 avril 2021À vous entendre j’ai un peu l’impression que c’est insoluble.
À titre personnel :
- j’aimais bien la démarcation bordure top du fieldset (au contraire même je trouve quelle améliore la lecture, enfin pour celui du premier niveau)
- je n’aime pas pour sûr non plus le dégradé de bordure sur la proposition de Rasta
- et je ne suis pas choqué du tout par le "cadre" de la proposition de Nicod ;Ce qui me gène par contre un peu plus c’est de démarquer le premier niveau de fieldset ; ou alors il faudrait pouvoir le désactiver avec une classe.
Je comprends l’argument que tu disais pour "si tu demandes une date en 3 parties jour | mois | annee" (ou je sais plus exactement) tu as besoin que ça se démarque.
Mais pour pas mal de formulaires utilisés dans SPIP démarquer plus le fieldset de premier niveau est pas utile (d’où peut être de pouvoir désactiver au besoin son décalage). Si tu regardes ?exec=configurer_contenu : il n’ a pas besoin de plus que ça actuellement.Maintenant si ça doit être fait quand même, ce que propose Nicod me parait vaguement plus agréable, même si c’est peut être pas assez distinctif. J’enlèverais la marge blanche entre le bord et le premier fieldset également.
Quelques remarques d’alignement :¶
- Par ailleurs je crois que (comme le montre Nicod) il faut réaligner le legend avec les labels dessous.
- Je dirais même qu’il faut aligner ce legend avec les labels au dessus (c’est à dire en soustrayant de la marge l’éventuelle bordure ajoutée)
- Il ne faudrait pas qu’une éventuelle bordure gauche sur le fieldset dépasse vers le bas (comme encore une fois ce que montre Nicod) ; Ce que je n’ai pas spécialement réussi à faire sur les captures que je montre après (peut être faut décorer la bordure avec un :before {} alors plutôt que de tenter d’altérer les marges des :last-child contenus dans le fieldset)Je montre différents tests ensuite, pour montrer que mettre un fieldset de premier niveau "visible" c’est pas gégé sur les formulaires de base, et mieux sans (ou faut un truc pour le désactiver - ou inversement l’activer au besoin). En fait il y a peut être besoin de 2 types de fieldsets (de premier niveau)
avec bordure gauche, sans marge gauche, alignements verticaux respectés¶
Ici le fieldset de premier niveau est bien lourd…
sans bordure gauche de premier niveau, alignements verticaux respectés¶
Le problème est montré sur le dernier champ du formulaire formidable : on ne sait pas s’il est du fieldset ou possiblement en dehors du fieldset
Bref, tout ça est hyper pas simple. Je n’ai pas l’impression qu’on puisse concilier l’un (la simplicité du premier niveau) sans alourdir visuellement inutilement, et sans proposer 2 « types » de fieldset de premier niveau.
Je parle même pas de la syntaxe avec ou sans div.fieldset en plus…