File size: 4,653 Bytes
fd0ebb4
 
c35fd71
d0ae45d
 
 
 
 
 
 
 
 
fd0ebb4
 
d0ae45d
 
 
 
 
 
 
 
fd0ebb4
cd6602e
d0ae45d
 
 
fbfbcdc
be6de26
ccf4167
d0ae45d
 
fd0ebb4
1d798d5
 
 
d0ae45d
 
a495513
1d798d5
fd0ebb4
7dd0d49
 
 
 
 
 
 
 
 
64b9903
 
7dd0d49
 
d0ae45d
7dd0d49
 
ccf4167
7dd0d49
 
 
 
 
 
 
181910d
7dd0d49
 
 
 
4bdf495
7dd0d49
 
 
 
 
 
 
 
 
 
 
 
 
 
4bdf495
7dd0d49
 
 
 
 
64b9903
7dd0d49
f57b99d
4bdf495
 
 
7dd0d49
 
 
fbfbcdc
7dd0d49
64b9903
7dd0d49
d0ae45d
7dd0d49
d0ae45d
 
7dd0d49
 
 
 
 
d0ae45d
fbfbcdc
d0ae45d
fbfbcdc
 
d0ae45d
4bdf495
7dd0d49
 
 
4bdf495
 
f57b99d
7dd0d49
 
fbfbcdc
 
e51f5e1
 
 
 
7dd0d49
 
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
from fastapi.middleware.cors import CORSMiddleware
from fastapi.responses import FileResponse
from starlette.background import BackgroundTask
import subprocess
import os
import uuid
import json
import requests
import time
import hashlib
import re
import urllib.parse

app = FastAPI()

app.add_middleware(
    CORSMiddleware,
    allow_origins=["*"],
    allow_credentials=True,
    allow_methods=["*"],
    allow_headers=["*"],
)

TEMP_DIR = "/tmp/fb_cache"
if not os.path.exists(TEMP_DIR):
    os.makedirs(TEMP_DIR)

MAX_FILE_AGE = 1800 

def cleanup(file_path: str):
    if os.path.exists(file_path):
        os.remove(file_path)

def clean_fb_url(url: str):
    if not url: return None
    url = url.replace('\\/', '/')
    try:
        url = json.loads(f'"{url}"')
    except: pass
    return urllib.parse.unquote(url).replace('&', '&')

def get_ffprobe_info(file_path):

    try:
        cmd = ['ffprobe', '-v', 'error', '-show_entries', 'stream=codec_type', '-of', 'json', file_path]
        result = subprocess.run(cmd, capture_output=True, text=True)
        data = json.loads(result.stdout)
        return [s['codec_type'] for s in data.get('streams', [])]
    except: return []

@app.get("/")
def root():
    return {"message": "Bumiz Facebook Pro API Active"}


@app.post("/download-private")
async def download_private_fb(payload: dict = Body(...)):
    html_source = payload.get("html", "")
    target_quality = payload.get("quality", "original") # original, 720, 480, 240

    if not html_source:
        return {"success": False, "error": "HTML Source is empty."}

    # Video & Audio Extraction Logic
    video_url = None
    audio_url = None

    # HD သို့မဟုတ် Progressive Link ကို အရင်ရှာခြင်း
    hd_match = re.search(r'"browser_native_hd_url":"([^"]+)"', html_source)
    sd_match = re.search(r'"browser_native_sd_url":"([^"]+)"', html_source)
    
    if hd_match: video_url = clean_fb_url(hd_match.group(1))
    elif sd_match: video_url = clean_fb_url(sd_match.group(1))

    # Separate Streams ရှာဖွေခြင်း
    v_matches = re.findall(r'"mime_type":"video[^"]+".*?"base_url":"([^"]+)"', html_source)
    a_matches = re.findall(r'"mime_type":"audio[^"]+".*?"base_url":"([^"]+)"', html_source)

    if not video_url and v_matches: video_url = clean_fb_url(v_matches[0])
    if a_matches: audio_url = clean_fb_url(a_matches[0])

    if not video_url:
        return {"success": False, "error": "Video link not found in source."}

    file_id = hashlib.md5(f"{video_url}_{target_quality}".encode()).hexdigest()
    final_video = os.path.join(TEMP_DIR, f"{file_id}.mp4")
    
    # Cache Check
    if os.path.exists(final_video):
        os.utime(final_video, None)
        return {"success": True, "method": "Cache", "video_url": f"get_file?id={file_id}.mp4", "size": os.path.getsize(final_video)}

    # Processing
    try:
        v_tmp = os.path.join(TEMP_DIR, f"{uuid.uuid4()}_v.mp4")
        a_tmp = os.path.join(TEMP_DIR, f"{uuid.uuid4()}_a.mp3")
        
        # Download streams
        headers = {'User-Agent': 'Mozilla/5.0'}
        with open(v_tmp, 'wb') as f: f.write(requests.get(video_url, headers=headers).content)
        if audio_url:
            with open(a_tmp, 'wb') as f: f.write(requests.get(audio_url, headers=headers).content)

        # Build FFmpeg Command (Force H.264 & AAC)
        cmd = ['ffmpeg', '-y', '-i', v_tmp]
        if os.path.exists(a_tmp) and os.path.getsize(a_tmp) > 1000:
            cmd += ['-i', a_tmp, '-map', '0:v:0', '-map', '1:a:0']
        
        # Quality Scaling if needed
        if target_quality != "original":
            cmd += ['-vf', f"scale=w='trunc(oh*a/2)*2':h={target_quality}"]
            
        cmd += ['-c:v', 'libx264', '-preset', 'ultrafast', '-crf', '23', '-c:a', 'aac', '-b:a', '128k', '-movflags', '+faststart', final_video]
        
        subprocess.run(cmd, check=True, capture_output=True)

        if os.path.exists(v_tmp): os.remove(v_tmp)
        if os.path.exists(a_tmp): os.remove(a_tmp)

        return {
            "success": True,
            "method": "Bumiz Engine",
            "video_url": f"get_file?id={file_id}.mp4",
            "size": os.path.getsize(final_video)
        }
    except Exception as e:


        return {"success": False, "error": str(e)}

@app.get("/get_file")
async def get_file(id: str):
    file_path = os.path.join(TEMP_DIR, id)
    if os.path.exists(file_path):
        return FileResponse(file_path, media_type="video/mp4", filename=f"fb_bumiz_{id}", background=BackgroundTask(cleanup, file_path))
    raise HTTPException(status_code=404)