Repository: yt-dlp/yt-dlp

Issue:
outtmpl problem with FFmpegExtractAudio
### DO NOT REMOVE OR SKIP THE ISSUE TEMPLATE

- [X] I understand that I will be **blocked** if I remove or skip any mandatory\* field

### Checklist

- [X] I'm reporting a bug unrelated to a specific site
- [X] I've verified that I'm running yt-dlp version **2023.01.02** ([update instructions](https://github.com/yt-dlp/yt-dlp#update)) or later (specify commit)
- [X] I've checked that all provided URLs are playable in a browser with the same IP and same login details
- [X] I've checked that all URLs and arguments with special characters are [properly quoted or escaped](https://github.com/yt-dlp/yt-dlp/wiki/FAQ#video-url-contains-an-ampersand--and-im-getting-some-strange-output-1-2839-or-v-is-not-recognized-as-an-internal-or-external-command)
- [X] I've searched the [bugtracker](https://github.com/yt-dlp/yt-dlp/issues?q=) for similar issues **including closed ones**. DO NOT post duplicates
- [X] I've read the [guidelines for opening an issue](https://github.com/yt-dlp/yt-dlp/blob/master/CONTRIBUTING.md#opening-an-issue)

### Provide a description that is worded well enough to be understood

Hi, I have a python program that uses yt-dlp embedded perfectly for downloading videos.
I tried to download some videos as audio files following the example, but after the conversion the file I get is called ".m4a". completely loses the filename.
The problem happens when I pass the "outtmpl" parameter. I tried passing a full path with filename ("//mnt/nas/Youtube Buddy Downloads/temp/Lento Violento - LENTO VIOLENTO - SPINGE MAS (MANTRA DAG PSICO LOOP MIX)"), or just a filename ("test ").

```
nome = //mnt/nas/Youtube Buddy Downloads/temp/Lento Violento - LENTO VIOLENTO - SPINGE MAS (MANTRA DAG PSICO LOOP MIX)
ydl_opts = {
    'format': 'm4a/bestaudio/best',
    'outtmpl': nome,
    'postprocessors': [{
        'key': 'FFmpegExtractAudio',
        'preferredcodec': 'm4a',
    }]
}
with yt_dlp.YoutubeDL(ydl_opts) as ydl:
    ydl.download([id_video])
```

### Provide verbose output that clearly demonstrates the problem

- [X] Run **your** yt-dlp command with **-vU** flag added (`yt-dlp -vU <your command line>`)
- [X] Copy the WHOLE output (starting with `[debug] Command-line config`) and insert it below

### Complete Verbose Output

```shell
[youtube] Extracting URL: -frfnDl8u_E
[youtube] -frfnDl8u_E: Downloading webpage
[youtube] -frfnDl8u_E: Downloading android player API JSON
[info] -frfnDl8u_E: Downloading 1 format(s): 140
[download] Destination: //mnt/nas/Youtube Buddy Downloads/temp/Lento Violento - LENTO VIOLENTO - SPINGE MAS (MANTRA DAG PSICO LOOP MIX)
[download] 100% of    4.08MiB in 00:00:00 at 11.15MiB/s
[FixupM4a] Correcting container of "//mnt/nas/Youtube Buddy Downloads/temp/Lento Violento - LENTO VIOLENTO - SPINGE MAS (MANTRA DAG PSICO LOOP MIX)"
[ExtractAudio] Destination: .m4a
Deleting original file //mnt/nas/Youtube Buddy Downloads/temp/Lento Violento - LENTO VIOLENTO - SPINGE MAS (MANTRA DAG PSICO LOOP MIX) (pass -k to keep)
[MoveFiles] Moving file ".m4a" to "//mnt/nas/Youtube Buddy Downloads/temp/.m4a"
```



Discussion:
Add `.%(ext)s` to the end of outtmpl
For devs:

The bug is in https://github.com/yt-dlp/yt-dlp/blob/ce03e9b90acef7a8b59b1193e32cbd9898c93ad0/yt_dlp/postprocessor/ffmpeg.py#L511-L512

This comment is no longer applicable in Py3 and we should use the proper method
yt-dl uses `os.path.splitext()` in 5 extractors, 2 postprocessors and 4 core files. Only in this one case out of two in `youtube_dl/postprocessor/ffmpeg.py` is its use avoided.

Considering that
* Blame shows that the comment is more than 8 years old
* yt-dl has no issues mentioning the problem in the comment
* there's no suggestion of the problem in the Python 2.6 documentation
* all yt-dl's other uses of `os.path.splitext()` don't seem to be failing,

now I would say it's super-fine to
>... use the proper method

in yt-dl too.

And if there was a problem it should have been addressed by a `compat_splitext()` function.

Also, note `utils.replace_extension()`!

Resolving patch:
diff --git a/yt_dlp/__init__.py b/yt_dlp/__init__.py
--- a/yt_dlp/__init__.py
+++ b/yt_dlp/__init__.py
@@ -318,10 +318,6 @@ def validate_outtmpl(tmpl, msg):
     if outtmpl_default == '':
         opts.skip_download = None
         del opts.outtmpl['default']
-    if outtmpl_default and not os.path.splitext(outtmpl_default)[1] and opts.extractaudio:
-        raise ValueError(
-            'Cannot download a video and extract audio into the same file! '
-            f'Use "{outtmpl_default}.%(ext)s" instead of "{outtmpl_default}" as the output template')
 
     def parse_chapters(name, value):
         chapters, ranges = [], []
diff --git a/yt_dlp/postprocessor/ffmpeg.py b/yt_dlp/postprocessor/ffmpeg.py
--- a/yt_dlp/postprocessor/ffmpeg.py
+++ b/yt_dlp/postprocessor/ffmpeg.py
@@ -508,8 +508,7 @@ def run(self, information):
         if acodec != 'copy':
             more_opts = self._quality_args(acodec)
 
-        # not os.path.splitext, since the latter does not work on unicode in all setups
-        temp_path = new_path = f'{path.rpartition(".")[0]}.{extension}'
+        temp_path = new_path = replace_extension(path, extension, information['ext'])
 
         if new_path == path:
             if acodec == 'copy':


Test patch: