Skip to content

When disconnecting the bot during audio playback, ffmpeg continues to lock the file. #2865

@creeper-0910

Description

@creeper-0910

Summary

When disconnect the bot while audio is playing, the ffmpeg process remains and locks the file, so it seems that the file cannot be deleted unless the bot is restarted.

Reproduction Steps

  1. Connect the bot to VC.
  2. With the bot playing audio, right-click on the bot and disconnect it from VC.
  3. Try to delete the file.

Minimal Reproducible Code

Details
import asyncio
import os
import logging
import discord
import ctypes
from ctypes import wintypes
from dotenv import load_dotenv

load_dotenv()

logging.basicConfig(level=logging.INFO)

bot = discord.Bot(intents=discord.Intents.all())
GENERIC_READ = 0x80000000
GENERIC_WRITE = 0x40000000
DELETE = 0x00010000
FILE_SHARE_NONE = 0
OPEN_EXISTING = 3
FILE_ATTRIBUTE_NORMAL = 0x80

CreateFileW = ctypes.windll.kernel32.CreateFileW
CreateFileW.restype = wintypes.HANDLE
CreateFileW.argtypes = [
    wintypes.LPCWSTR,
    wintypes.DWORD,
    wintypes.DWORD,
    wintypes.LPVOID,
    wintypes.DWORD,
    wintypes.DWORD,
    wintypes.HANDLE,
]
CloseHandle = ctypes.windll.kernel32.CloseHandle
GetLastError = ctypes.windll.kernel32.GetLastError

INVALID_HANDLE_VALUE = wintypes.HANDLE(-1).value


def is_file_locked(path):
    h = CreateFileW(
        path,
        GENERIC_READ | GENERIC_WRITE | DELETE,
        FILE_SHARE_NONE,
        None,
        OPEN_EXISTING,
        FILE_ATTRIBUTE_NORMAL,
        None,
    )
    if h == INVALID_HANDLE_VALUE:
        err = GetLastError()
        if err in (32, 33):  # ERROR_SHARING_VIOLATION, ERROR_LOCK_VIOLATION
            return True, err
        return None, err  # other errors: access denied, not found, etc.
    CloseHandle(h)
    return False, 0


@bot.event
async def on_ready():
    print(f"{bot.user} is ready and online!")


@bot.slash_command(name="play")
async def play(ctx: discord.ApplicationContext):
    await ctx.defer()
    vc = await ctx.user.voice.channel.connect()
    await vc.play(
        discord.FFmpegPCMAudio(
            "test.wav",
            options="-reconnect 1 -reconnect_streamed 1 -reconnect_delay_max 5",
        ),
        wait_finish=True,
    )
    await vc.disconnect()
    await ctx.followup.send("end")


@bot.event
async def on_voice_state_update(
    member: discord.Member, _: discord.VoiceState, after: discord.VoiceState
):
    if member == bot.user and after.channel is None:
        await asyncio.sleep(2)
        print("File is locked:", is_file_locked("test.wav"))


bot.run(os.getenv("TOKEN"))

Expected Results

The file will be deleted without error.

Actual Results

PermissionError: [WinError 32] The process cannot access the file because it is being used by another process.: '2KuYh4FdZgM3t_m8.wav'

Intents

all

System Information

  • Python v3.12.10-final
  • py-cord v2.6.1-final
  • aiohttp v3.12.15
  • system info: Windows 11 10.0.26100

Checklist

  • I have searched the open issues for duplicates.
  • I have shown the entire traceback, if possible.
  • I have removed my token from display, if visible.

Additional Context

No response

Metadata

Metadata

Assignees

No one assigned

    Labels

    bugSomething isn't working

    Type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions