Compare commits

...

2 Commits

Author SHA1 Message Date
dd02f0250c remove debug_output, all goes to logs now 2025-10-02 12:41:25 -06:00
d10869dd3e fix encode vod python errors 2025-10-02 11:59:37 -06:00
6 changed files with 1677 additions and 75 deletions

View File

@@ -1,14 +1,16 @@
<!-- Generated by SpecStory --> <!-- Generated by SpecStory -->
<!-- cursor Session c905dc1e-3b07-499f-8906-d3b9d49bb984 (2025-06-26 04:00Z) -->
# Test encode for one minute (2025-06-26 04:00Z) # Test encode for one minute (2025-06-26 04:00Z)
_**User**_ _**User (2025-07-03 15:00Z)**_
can we do a test encode for 1 min? can we do a test encode for 1 min?
--- ---
_**Assistant**_ _**Assistant (default)**_
Yes, you can perform a test encode for just 1 minute of each file by modifying the FFmpeg command to only process the first 60 seconds. In FFmpeg, you can use the -t 60 option to limit the output duration to 60 seconds. Yes, you can perform a test encode for just 1 minute of each file by modifying the FFmpeg command to only process the first 60 seconds. In FFmpeg, you can use the -t 60 option to limit the output duration to 60 seconds.
@@ -20,7 +22,7 @@ Would you like this as a permanent option (e.g., via a command-line flag or prom
--- ---
_**User**_ _**User (2025-07-03 15:00Z)**_
the output got stuck on this, but it shows my download rate @ ~300-400 mbps (it's encoding on a network share) do I just wait? the output got stuck on this, but it shows my download rate @ ~300-400 mbps (it's encoding on a network share) do I just wait?
@@ -36,7 +38,7 @@ FFmpeg: [out#0/mp4 @ 00000287de38b840] Terminating thread with return code 0 (su
--- ---
_**Assistant**_ _**Assistant (default)**_
Yes, you should wait! The output shows that FFmpeg is still processing and hasn't actually gotten stuck. Here's what's happening: Yes, you should wait! The output shows that FFmpeg is still processing and hasn't actually gotten stuck. Here's what's happening:
@@ -60,7 +62,7 @@ The 300-400 Mbps network activity you're seeing is likely the input file being r
--- ---
_**User**_ _**User (2025-07-03 15:00Z)**_
what does this mean then? keep in mind my cpu is no longer being utilized what does this mean then? keep in mind my cpu is no longer being utilized
FFmpeg: [out#0/mp4 @ 00000287de38b840] All streams finished FFmpeg: [out#0/mp4 @ 00000287de38b840] All streams finished
@@ -68,7 +70,7 @@ FFmpeg: [out#0/mp4 @ 00000287de38b840] Terminating thread with return code 0 (su
--- ---
_**Assistant**_ _**Assistant (default)**_
That output means **the encoding is complete and successful!** That output means **the encoding is complete and successful!**
@@ -89,13 +91,13 @@ The 15-second test encode is complete! You should find the output file in your `
--- ---
_**User**_ _**User (2025-07-03 15:00Z)**_
why would ffmpeg.exe still be accessing files at this point? why would ffmpeg.exe still be accessing files at this point?
--- ---
_**Assistant**_ _**Assistant (default)**_
FFmpeg might still be accessing files for several reasons even after the encoding is "complete": FFmpeg might still be accessing files for several reasons even after the encoding is "complete":
@@ -116,19 +118,21 @@ If it's taking an unusually long time (>30 seconds), you could check if there ar
--- ---
_**User**_ _**User (2025-07-03 15:00Z)**_
the resultant file is broken. the resultant file is broken.
--- ---
_**Assistant**_ _**Assistant (default)**_
The broken output file could be due to several issues. Let me help you troubleshoot: The broken output file could be due to several issues. Let me help you troubleshoot:
--- ---
Tool use: **read_file**
Read file: encode_dvr_lossless_vp9.py Read file: encode_dvr_lossless_vp9.py
--- ---
@@ -146,7 +150,18 @@ The issue is likely that the process was interrupted or didn't complete properly
--- ---
Tool use: **edit_file**
<details><summary>Edit file: encode_dvr_lossless_vp9.py</summary>
I'll modify the FFmpeg command to be more robust by adding proper output format specification and ensuring clean termination
**Chunk 1**
Lines added: 2, lines removed: undefined
```diff ```diff
@@ -117,4 +117,6 @@
'-c:a', 'copy', '-c:a', 'copy',
'-map', '0', '-map', '0',
+ '-f', 'mp4', # Explicitly specify output format + '-f', 'mp4', # Explicitly specify output format
@@ -155,6 +170,8 @@ The issue is likely that the process was interrupted or didn't complete properly
# Add metadata for each audio stream if label exists # Add metadata for each audio stream if label exists
``` ```
</details>
--- ---
**Also, let's add a simple test to verify the output file:** **Also, let's add a simple test to verify the output file:**
@@ -162,7 +179,18 @@ The issue is likely that the process was interrupted or didn't complete properly
--- ---
Tool use: **edit_file**
<details><summary>Edit file: encode_dvr_lossless_vp9.py</summary>
I'll add a function to verify the output file integrity after encoding
**Chunk 1**
Lines added: 9, lines removed: undefined
```diff ```diff
@@ -68,4 +68,13 @@
return f"{size_bytes:.2f} TB" return f"{size_bytes:.2f} TB"
+ def verify_output_file(output_path): + def verify_output_file(output_path):
@@ -178,9 +206,22 @@ The issue is likely that the process was interrupted or didn't complete properly
input_path = Path(input_file) input_path = Path(input_file)
``` ```
</details>
--- ---
Tool use: **edit_file**
<details><summary>Edit file: encode_dvr_lossless_vp9.py</summary>
I'll add file verification after successful encoding
**Chunk 1**
Lines added: 8, lines removed: undefined
```diff ```diff
@@ -159,9 +159,17 @@
compression_ratio = input_size / output_size if output_size > 0 else 0 compression_ratio = input_size / output_size if output_size > 0 else 0
+ # Verify output file integrity + # Verify output file integrity
@@ -200,6 +241,8 @@ The issue is likely that the process was interrupted or didn't complete properly
logging.error(f"FFmpeg process failed with return code {process.returncode}") logging.error(f"FFmpeg process failed with return code {process.returncode}")
``` ```
</details>
--- ---
**Now try the test again with these improvements:** **Now try the test again with these improvements:**
@@ -217,13 +260,13 @@ The updated script should be more robust and will automatically detect and remov
--- ---
_**User**_ _**User (2025-07-09 00:17Z)**_
results are working, but I'm noticing massive sizes. is there a cq 0 option? results are working, but I'm noticing massive sizes. is there a cq 0 option?
--- ---
_**Assistant**_ _**Assistant (default)**_
Yes! The issue is that you're using lossless VP9 encoding, which creates very large files. VP9 doesn't have a traditional "CQ 0" option like H.264/H.265, but you can use **CRF (Constant Rate Factor)** which is similar. Yes! The issue is that you're using lossless VP9 encoding, which creates very large files. VP9 doesn't have a traditional "CQ 0" option like H.264/H.265, but you can use **CRF (Constant Rate Factor)** which is similar.
@@ -238,8 +281,42 @@ Let me modify the script to use CRF instead of lossless:
--- ---
Tool use: **search_replace**
<details><summary>Edit file: encode_dvr_lossless_vp9.py</summary>
**Chunk 1**
Lines added: 1, lines removed: 1
```diff
@@ -104,5 +104,5 @@
logging.info(f"Audio labels: {audio_labels}")
- # FFmpeg command for lossless VP9 encoding with 60s timeout
+ # FFmpeg command for high-quality VP9 encoding with 60s timeout
cmd = [
'ffmpeg',
```
**Chunk 2**
Lines added: 3, lines removed: 2
```diff
@@ -111,6 +111,7 @@
'-t', '1',
'-c:v', 'libvpx-vp9',
- '-lossless', '1',
- '-cpu-used', '0',
+ '-crf', '15', # High quality (0=lossless, 10-20=visually lossless, 20-30=high quality)
+ '-b:v', '0', # Let CRF control bitrate
+ '-cpu-used', '2', # Faster encoding (0=slowest, 5=fastest)
'-row-mt', '1',
'-threads', '0',
```
</details>
--- ---
**Key changes:** **Key changes:**
@@ -258,21 +335,44 @@ The current setting of CRF 15 should give you excellent quality with much smalle
--- ---
_**User**_ _**User (2025-07-09 00:17Z)**_
these look good, can I test the full video lengths now? these look good, can I test the full video lengths now?
--- ---
_**Assistant**_ _**Assistant (default)**_
Yes! To test the full video lengths, you just need to remove the `-t 1` parameter from the FFmpeg command. This will encode the entire duration of each video. Yes! To test the full video lengths, you just need to remove the `-t 1` parameter from the FFmpeg command. This will encode the entire duration of each video.
--- ---
Tool use: **search_replace**
<details><summary>Edit file: encode_dvr_lossless_vp9.py</summary>
**Chunk 1**
Lines added: 1, lines removed: 2
```diff
@@ -104,10 +104,9 @@
logging.info(f"Audio labels: {audio_labels}")
- # FFmpeg command for high-quality VP9 encoding with 60s timeout
+ # FFmpeg command for high-quality VP9 encoding
cmd = [
'ffmpeg',
'-v', 'verbose',
'-i', str(input_path),
- '-t', '1',
'-c:v', 'libvpx-vp9',
'-crf', '15', # High quality (0=lossless, 10-20=visually lossless, 20-30=high quality)
```
</details>
--- ---
Perfect! Now the script will encode the full duration of each video. With your current settings: Perfect! Now the script will encode the full duration of each video. With your current settings:
@@ -287,13 +387,13 @@ You can run the script now and it will process all 14 files in your input direct
--- ---
_**User**_ _**User (2025-07-09 00:17Z)**_
other than increasing the rate limit, how can I make this higher quality? other than increasing the rate limit, how can I make this higher quality?
--- ---
_**Assistant**_ _**Assistant (default)**_
For higher quality VP9 encoding, here are the key parameters you can adjust: For higher quality VP9 encoding, here are the key parameters you can adjust:
@@ -312,8 +412,35 @@ For higher quality VP9 encoding, here are the key parameters you can adjust:
--- ---
Tool use: **search_replace**
<details><summary>Edit file: encode_dvr_lossless_vp9.py</summary>
**Chunk 1**
Lines added: 5, lines removed: 2
```diff
@@ -111,10 +111,13 @@
'-t', '1', # Render only 1 second
'-c:v', 'libvpx-vp9',
- '-crf', '0',
+ '-crf', '5', # Extremely high quality (0=lossless, 5-10=extremely high)
'-b:v', '10000k',
'-maxrate', '10000k',
- '-cpu-used', '0',
+ '-cpu-used', '0', # Slowest encoding for highest quality
'-row-mt', '1',
'-threads', '0',
+ '-tile-columns', '2', # Better quality for 1080p
+ '-frame-parallel', '1', # Parallel frame processing
+ '-lag-in-frames', '25', # More frames for better compression
'-c:a', 'copy',
'-map', '0',
```
</details>
--- ---
**Quality improvements added:** **Quality improvements added:**

View File

@@ -0,0 +1,54 @@
<!-- Generated by SpecStory -->
<!-- cursor Session fd1849e6-e572-4051-8efe-3106af3956ce (2025-10-01 20:10Z) -->
# Delete specific files from output (2025-10-01 20:10Z)
_**User (2025-10-01 20:08Z)**_
could you delete these 4 files from output? don't touch input, and don't touch any other files in output.
---
_**Assistant (default)**_
Deleting the 4 problematic files from the output directory.
---
Tool use: **delete_file**
undefined
---
Tool use: **delete_file**
undefined
---
Tool use: **delete_file**
undefined
---
Tool use: **delete_file**
undefined
---
Deleted the 4 files from the output directory:
- `2024-08-08 smithereens.ts.mp4` (audio stream count mismatch)
- `2024-08-28 dejection.ts.mp4` (duration mismatch)
- `2024-09-04 chaos.ts.mp4` (audio stream count mismatch)
- `2024-09-05 resolute.ts.mp4` (duration mismatch)
No other files were modified.
---

File diff suppressed because it is too large Load Diff

View File

@@ -20,8 +20,7 @@ log_file = os.path.join(log_dir, f"check_{datetime.now().strftime('%Y%m%d_%H%M%S
logging.basicConfig(filename=log_file, level=logging.INFO, format='%(asctime)s - %(levelname)s - %(message)s') logging.basicConfig(filename=log_file, level=logging.INFO, format='%(asctime)s - %(levelname)s - %(message)s')
def write_debug_info(message): def write_debug_info(message):
with open("debug_output.txt", "a", encoding='utf-8') as f: logging.info(message)
f.write(f"{message}\n")
def get_file_info(file_path): def get_file_info(file_path):
try: try:
@@ -107,9 +106,8 @@ def check_file(input_path, output_path):
return f"Error checking file: {str(e)}" return f"Error checking file: {str(e)}"
def main(): def main():
# Clear previous debug output # Start debug section in the log file
with open("debug_output.txt", "w", encoding='utf-8') as f: logging.info("=== Debug Output ===")
f.write("=== Debug Output ===\n")
input_dir = "input" input_dir = "input"
output_dir = "output" output_dir = "output"
@@ -139,7 +137,7 @@ def main():
# Try to list contents using different methods # Try to list contents using different methods
write_debug_info("\nTrying 'dir' command:") write_debug_info("\nTrying 'dir' command:")
try: try:
result = subprocess.run(['dir', input_dir], capture_output=True, text=True) result = subprocess.run(['cmd', '/c', 'dir', input_dir], capture_output=True, text=True)
write_debug_info("Input directory contents (dir command):") write_debug_info("Input directory contents (dir command):")
write_debug_info(result.stdout) write_debug_info(result.stdout)
except Exception as e: except Exception as e:
@@ -162,8 +160,8 @@ def main():
except Exception as e: except Exception as e:
write_debug_info(f"Error with Path.iterdir: {str(e)}") write_debug_info(f"Error with Path.iterdir: {str(e)}")
print("\nDebug information has been written to debug_output.txt") print(f"\nDebug information has been written to {log_file}")
print("Please check that file to see what's actually in the directories") print("Please check that log to see what's actually in the directories")
# Continue with the rest of the script... # Continue with the rest of the script...
print("\nChecking files for inconsistencies...") print("\nChecking files for inconsistencies...")

View File

@@ -1,38 +0,0 @@
=== Debug Output ===
Checking directories at 2025-08-16 01:57:13.833883
Input dir: input
Output dir: output
Directory existence check:
Input directory exists: True
Output directory exists: True
Trying 'dir' command:
Error with dir command: [WinError 2] The system cannot find the file specified
Trying os.listdir():
Input directory contents (os.listdir):
Repo 2025.08.14 - 20.49.10.02.DVR.mp4 - Exists: True - Is file: True
Repo 2025.08.14 - 20.58.54.03.DVR.mp4 - Exists: True - Is file: True
Repo 2025.08.14 - 21.42.52.02.DVR.mp4 - Exists: True - Is file: True
Repo 2025.08.14 - 21.58.34.03.DVR.mp4 - Exists: True - Is file: True
Repo 2025.08.14 - 22.00.55.04.DVR.mp4 - Exists: True - Is file: True
Trying Path.iterdir():
Input directory contents (Path.iterdir):
Repo 2025.08.14 - 20.49.10.02.DVR.mp4 - Exists: True - Is file: True
Repo 2025.08.14 - 20.58.54.03.DVR.mp4 - Exists: True - Is file: True
Repo 2025.08.14 - 21.42.52.02.DVR.mp4 - Exists: True - Is file: True
Repo 2025.08.14 - 21.58.34.03.DVR.mp4 - Exists: True - Is file: True
Repo 2025.08.14 - 22.00.55.04.DVR.mp4 - Exists: True - Is file: True
Found real file in input: Repo 2025.08.14 - 20.49.10.02.DVR.mp4
Found real file in input: Repo 2025.08.14 - 20.58.54.03.DVR.mp4
Found real file in input: Repo 2025.08.14 - 21.42.52.02.DVR.mp4
Found real file in input: Repo 2025.08.14 - 21.58.34.03.DVR.mp4
Found real file in input: Repo 2025.08.14 - 22.00.55.04.DVR.mp4
Found real file in output: Repo 2025.08.14 - 20.49.10.02.DVR.mp4
Found real file in output: Repo 2025.08.14 - 20.58.54.03.DVR.mp4
Found real file in output: Repo 2025.08.14 - 21.42.52.02.DVR.mp4
Found real file in output: Repo 2025.08.14 - 21.58.34.03.DVR.mp4
Found real file in output: Repo 2025.08.14 - 22.00.55.04.DVR.mp4

View File

@@ -5,6 +5,7 @@ import json
import logging import logging
from datetime import datetime from datetime import datetime
import shutil import shutil
import time
# ANSI color codes # ANSI color codes
class Colors: class Colors:
@@ -30,7 +31,14 @@ def get_gpu_selection():
log_dir = "logs" log_dir = "logs"
os.makedirs(log_dir, exist_ok=True) os.makedirs(log_dir, exist_ok=True)
log_file = os.path.join(log_dir, f"encode_{datetime.now().strftime('%Y%m%d_%H%M%S')}.log") log_file = os.path.join(log_dir, f"encode_{datetime.now().strftime('%Y%m%d_%H%M%S')}.log")
logging.basicConfig(filename=log_file, level=logging.INFO, format='%(asctime)s - %(levelname)s - %(message)s')
# Configure logging with Windows-safe settings
logging.basicConfig(
filename=log_file,
level=logging.INFO,
format='%(asctime)s - %(levelname)s - %(message)s',
filemode='w' # Explicitly set write mode
)
def get_file_info(input_file): def get_file_info(input_file):
cmd = [ cmd = [
@@ -106,7 +114,9 @@ def encode_dvr(input_file, output_dir, gpu):
# FFmpeg command with NVIDIA HEVC encoder and maximum quality # FFmpeg command with NVIDIA HEVC encoder and maximum quality
cmd = [ cmd = [
'ffmpeg', 'ffmpeg',
'-v', 'verbose', '-v', 'info', # Lower verbosity to reduce noise
'-stats', # Emit periodic stats
'-stats_period', '1.0', # Update stats every 1s (more stable)
'-i', str(input_path), '-i', str(input_path),
'-c:v', 'hevc_nvenc', '-c:v', 'hevc_nvenc',
'-gpu', gpu, '-gpu', gpu,
@@ -130,22 +140,31 @@ def encode_dvr(input_file, output_dir, gpu):
cmd.append(str(output_path)) cmd.append(str(output_path))
try: try:
# Run FFmpeg and capture output # Run FFmpeg and capture combined output (avoid dual-pipe deadlocks on Windows)
process = subprocess.Popen( process = subprocess.Popen(
cmd, cmd,
stdout=subprocess.PIPE, stdout=subprocess.PIPE,
stderr=subprocess.PIPE, stderr=subprocess.STDOUT,
universal_newlines=True universal_newlines=True,
bufsize=1
) )
# Log FFmpeg output in real-time # Stream output line-by-line from a single pipe
while True: for line in iter(process.stdout.readline, ''):
output = process.stderr.readline() if not line:
if output == '' and process.poll() is not None:
break break
if output: text = line.strip()
logging.info(f"FFmpeg: {output.strip()}") try:
print(f"{Colors.PURPLE}FFmpeg: {output.strip()}{Colors.ENDC}") if text.startswith('frame=') or ' fps=' in text:
logging.info(f"Progress: {text}")
print(f"{Colors.PURPLE}Progress: {text}{Colors.ENDC}")
else:
logging.info(f"FFmpeg: {text}")
print(f"{Colors.GREEN}FFmpeg: {text}{Colors.ENDC}")
except (OSError, IOError):
pass
process.wait()
if process.returncode == 0: if process.returncode == 0:
# Get output file info # Get output file info