Gemini API इमेज समझ: Python में इमेज इनपुट और इमेज-टू-टेक्स्ट

Python से Gemini API को फ़ोटो भेजें और टेक्स्ट वापस पाएँ। यह लेख इनलाइन बाइट्स, Files API और मल्टी-इमेज प्रॉम्प्ट दिखाता है, फिर वही कॉल कैप्शन, रसीद OCR और बाउंडिंग बॉक्स में बदलता है, साथ में टोकन गणित, साइज़ की सीमाएँ और आम एरर के समाधान भी।

Gemini API इमेज समझ: Python में इमेज इनपुट और इमेज-टू-टेक्स्ट
Cristian Da Conceicao
Picasso IA के संस्थापक

आपके पास एक फ़ोटो है और आपको उससे शब्द चाहिए। किसी प्रोडक्ट शॉट के लिए alt text चाहिए, किसी रसीद का कुल योग चाहिए, या किसी शेल्फ़ की गिनती चाहिए। Gemini API इमेज को प्रॉम्प्ट के हिस्से के रूप में लेता है और टेक्स्ट वापस भेजता है, इसलिए पूरा काम लगभग दस लाइन के एक Python कॉल में हो जाता है। यह लेख उसी क्रम में चलता है जिसमें समस्याएँ सामने आती हैं: सेटअप, इमेज भेजने के तीन तरीके, ऐसे प्रॉम्प्ट जो काम का टेक्स्ट लौटाएँ, टोकन की लागत, और वे गलतियाँ जो रिक्वेस्ट बर्बाद करती हैं।

नीचे के कोड के लिए एक बदलाव मायने रखता है। Google के मौजूदा डॉक्स Interactions API (client.interactions.create) के ज़रिए इमेज इनपुट दिखाते हैं और पुराने generateContent तरीके को लेगेसी बताते हैं, साथ ही यह भी पक्का करते हैं कि वह पूरी तरह समर्थित है। यहाँ दोनों वर्ज़न दिए गए हैं, ताकि आप अपने प्रोजेक्ट के हिसाब से जो चाहें इस्तेमाल कर सकें।

इमेज इनपुट असल में क्या करता है

लैपटॉप के बगल में प्रिंटेड मार्केट फ़ोटो पर फ़ोन पकड़े महिला

Gemini मॉडल मल्टीमॉडल हैं, यानी एक ही रिक्वेस्ट में टेक्स्ट पार्ट और इमेज पार्ट साथ-साथ हो सकते हैं। आप एक फ़ोटो के साथ एक इंस्ट्रक्शन भेजते हैं, और मॉडल टेक्स्ट में जवाब देता है। इसके लिए कोई अलग विज़न एंडपॉइंट नहीं चाहिए, कोई प्रीप्रोसेसिंग स्टेप नहीं चाहिए, और पहले कोई OCR लाइब्रेरी इंस्टॉल करने की ज़रूरत नहीं है। इमेज बस प्रॉम्प्ट का एक और हिस्सा है।

एक रिक्वेस्ट में इमेज से टेक्स्ट

वही कॉल पैटर्न बहुत अलग-अलग काम कर सकता है, यह इस पर निर्भर है कि आप कौन सी इंस्ट्रक्शन जोड़ते हैं:

  • कैप्शनिंग: सोशल पोस्ट या पेज के विवरण के लिए एक वाक्य।
  • Alt text: एक्सेसिबिलिटी के लिए छोटे, सीधे विवरण।
  • विज़ुअल सवाल: "मेज़ पर कितनी कुर्सियाँ हैं?" या "क्या लेबल सामने की ओर है?"
  • OCR: रसीदों, साइनबोर्ड, फ़ॉर्म और हाथ से लिखे नोट्स से निकाला गया टेक्स्ट।
  • डिटेक्शन: लेबल वाले बाउंडिंग बॉक्स, JSON में वापस।
  • तुलना: दो या उससे ज़्यादा इमेज के बीच अंतर।

💡 इंस्ट्रक्शन को ही प्रोडक्ट मानें। हर स्थिति में मॉडल वही रहता है। प्रॉम्प्ट तय करता है कि आपको फ़ोटो पर कविता मिलेगी या साफ़ JSON में कुल योग।

वे मॉडल जो इमेज स्वीकार करते हैं

Google का मॉडल्स पेज ये मौजूदा ID सूचीबद्ध करता है, और इन सभी में इमेज इनपुट है:

मॉडल IDस्थितिGoogle का विवरण
gemini-3.8-flashस्थिरसबसे बुद्धिमान Flash मॉडल
gemini-3.7-flashस्थिरजटिल कोडिंग और एजेंटिक वर्कफ़्लो
gemini-3.6-flashस्थिरसामान्य मल्टीमॉडल काम
gemini-3.5-flash (Gemini 3.5 Flash)स्थिरहाई-थ्रूपुट वर्कलोड
gemini-3.1-pro-preview (Gemini 3.1 Pro)प्रीव्यूजटिल समस्या-समाधान
gemini-3-flash-preview (Gemini 3 Flash)प्रीव्यूमल्टीमॉडल कार्य

लाइनअप तेज़ी से बदलते हैं, इसलिए प्रोडक्शन में कोई ID पक्की करने से पहले मॉडल्स पेज देख लें। इमेज के काम के लिए Flash मॉडल एक समझदार डिफ़ॉल्ट है। Pro मॉडल पर तभी जाएँ जब घने स्कैन या मुश्किल दृश्यों पर जवाब गलत आने लगें।

अपना Python एनवायरनमेंट सेट करें

शाम के समय खुले टर्मिनल के साथ अखरोट की मेज़ पर डेवलपर का लैपटॉप

अभी दो मिनट का सेटअप बाद में कई घंटे की उलझन भरी इम्पोर्ट एरर से बचाता है।

SDK इंस्टॉल करें

आधिकारिक पैकेज google-genai है। नीचे के उदाहरण स्ट्रक्चर्ड आउटपुट के लिए Pydantic और बॉक्स बनाने के लिए Pillow भी इस्तेमाल करते हैं।

pip install -U google-genai pydantic pillow

इसे पुराने google-generativeai पैकेज से न मिलाएँ। नया पैकेज from google import genai के नाम से इम्पोर्ट होता है, और यहाँ के हर स्निपेट में यही माना गया है।

क्लाइंट बनाएँ

Google AI Studio में एक क्रेडेंशियल बनाएँ, उसे उस एनवायरनमेंट वेरिएबल में रखें जिसका नाम Google के सेटअप पेज में लिखा है, और उसे सोर्स कंट्रोल से बाहर रखें। क्लाइंट उसे अपने आप पढ़ लेता है:

from google import genai

client = genai.Client()

कोई आर्गुमेंट नहीं, स्क्रिप्ट में कोई हार्डकोडेड सीक्रेट नहीं। इसके बाद के हर उदाहरण में यही client दोबारा इस्तेमाल होता है।

इमेज तीन तरीकों से भेजें

तरीका फ़ाइल के साइज़ और दोबारा इस्तेमाल के आधार पर चुनें, आदत के आधार पर नहीं।

छोटी फ़ाइलों के लिए इनलाइन बाइट्स

हार्बर टाउन की प्रिंट के सामने रखा कैमरा मेमरी कार्ड स्लॉट

इनलाइन डेटा सबसे छोटा रास्ता है। आप फ़ाइल पढ़ते हैं, उसे एन्कोड करते हैं और प्रॉम्प्ट के साथ भेजते हैं। मौजूदा Interactions API वर्ज़न ऐसा दिखता है:

import base64
from pathlib import Path

image_bytes = Path("street-market.jpg").read_bytes()

interaction = client.interactions.create(
    model="gemini-3.8-flash",
    input=[
        {"type": "text", "text": "Caption this image in one sentence."},
        {
            "type": "image",
            "data": base64.b64encode(image_bytes).decode("utf-8"),
            "mime_type": "image/jpeg",
        },
    ],
)

print(interaction.output_text)

पुराना generateContent वर्ज़न अब भी मान्य है और थोड़ा छोटा है, क्योंकि एन्कोडिंग SDK संभालता है:

from google.genai import types

response = client.models.generate_content(
    model="gemini-3.8-flash",
    contents=[
        types.Part.from_bytes(data=image_bytes, mime_type="image/jpeg"),
        "Caption this image in one sentence.",
    ],
)

print(response.text)

इनलाइन डेटा पूरी रिक्वेस्ट (प्रॉम्प्ट टेक्स्ट, सिस्टम इंस्ट्रक्शन और इमेज बाइट्स मिलाकर) को 20 MB तक सीमित करता है। एक फ़ोन फ़ोटो आराम से आ जाती है। पूरे रिज़ॉल्यूशन के स्कैन का बैच नहीं आता।

बड़ी इमेज के लिए Files API

बड़ी पहाड़ी झील की प्रिंट के बगल में हार्ड ड्राइव पकड़े फ़ोटोग्राफ़र

जब रिक्वेस्ट 20 MB से ऊपर जाएगी, या जब आप एक ही इमेज के बारे में कई सवाल पूछना चाहते हैं, तब उसे एक बार अपलोड करें और URI से रेफ़रेंस करें:

uploaded = client.files.upload(file="mountain-lake-print.jpg")

interaction = client.interactions.create(
    model="gemini-3.8-flash",
    input=[
        {"type": "text", "text": "Describe the scene and list any visible text."},
        {
            "type": "image",
            "uri": uploaded.uri,
            "mime_type": uploaded.mime_type,
        },
    ],
)

print(interaction.output_text)

अपलोड की गई फ़ाइलें अस्थायी रूप से रखी जाती हैं, इसलिए Files API को डिलीवरी का माध्यम मानें, आर्काइव नहीं। अपनी मूल फ़ाइलें अपने पास रखें।

एक प्रॉम्प्ट में कई इमेज

एक जैसे दो लिविंग रूम प्रिंट, जिनमें एक अंतर दिखाया गया है

उसी input लिस्ट में और इमेज पार्ट जोड़ें। Google के डॉक्स एक रिक्वेस्ट में 3,600 इमेज फ़ाइलों तक की अनुमति देते हैं।

before = client.files.upload(file="living-room-before.jpg")
after = client.files.upload(file="living-room-after.jpg")

interaction = client.interactions.create(
    model="gemini-3.8-flash",
    input=[
        {
            "type": "text",
            "text": "The first image is BEFORE and the second is AFTER. "
                    "What is different between them?",
        },
        {"type": "image", "uri": before.uri, "mime_type": before.mime_type},
        {"type": "image", "uri": after.uri, "mime_type": after.mime_type},
    ],
)

print(interaction.output_text)

टेक्स्ट में साफ़ बताएँ कि कौन सी इमेज कौन सी है। मॉडल एक क्रम वाली लिस्ट देखता है, और सिर्फ़ "इन्हें तुलना करें" लिखने पर वह भूमिकाओं को लेकर अनुमान लगाता रहता है।

प्रॉम्प्ट जो फ़ोटो को टेक्स्ट में बदलते हैं

कॉल कभी नहीं बदलती। सिर्फ़ इंस्ट्रक्शन बदलती है।

लक्ष्यप्रॉम्प्ट पैटर्नआउटपुट का रूप
कैप्शन"इस इमेज का एक वाक्य में कैप्शन लिखें।"सादा टेक्स्ट
Alt text"125 अक्षरों से कम का alt text लिखें। केवल वही बताएँ जो दिख रहा हो।"सादा टेक्स्ट
विज़ुअल सवाल"बाईं शेल्फ़ पर कितने लाल क्रेट हैं?"छोटा जवाब
एक्सट्रैक्शन"दुकान का नाम, तारीख और कुल योग निकालें।"स्कीमा के ज़रिए JSON
डिटेक्शन"इमेज की सभी प्रमुख चीज़ें डिटेक्ट करें।"स्कीमा के ज़रिए JSON

कैप्शन और Alt text

मॉनिटर के बगल में नोटबुक में alt text लिखता वेब एडिटर

सबसे बड़ा गुणवत्ता सुधार साफ़ सीमाएँ तय करने से आता है। "इस इमेज का वर्णन करें" एक पैराग्राफ़ लौटाता है। "125 अक्षरों से कम का alt text लिखें, 'image of' जैसी शुरुआत न हो" ऐसा कुछ लौटाता है जिसे आप प्रकाशित कर सकें।

prompt = (
    "Write alt text for this photo in under 125 characters. "
    "Describe only what is visible. Do not start with 'image of'."
)

एक सरल लूप से फ़ोटो के फ़ोल्डर पर यह चलाएँ, तो साइट के हर गायब alt attribute का पहला ड्राफ़्ट तैयार हो जाता है। फिर भी इंसान ड्राफ़्ट पढ़ता है, क्योंकि मॉडल किसी दृश्य में क्या ज़रूरी है, इसे गलत आंक सकता है।

OCR और रसीदें

कैफ़े काउंटर पर मुड़ी हुई रसीदें और हाथ से लिखी सूची

रसीदें अच्छी परीक्षा हैं, क्योंकि उनमें छपा टेक्स्ट, संख्याएँ और सिलवटें एक साथ होती हैं। गद्य के बजाय स्ट्रक्चर्ड आउटपुट माँगें। Pydantic से आकार तय करें और उसका JSON स्कीमा response_format के ज़रिए पास करें:

from pydantic import BaseModel

class LineItem(BaseModel):
    name: str
    price: float

class Receipt(BaseModel):
    merchant: str
    date: str
    items: list[LineItem]
    total: float

receipt = client.files.upload(file="receipt.jpg")

interaction = client.interactions.create(
    model="gemini-3.8-flash",
    input=[
        {
            "type": "text",
            "text": "Extract the merchant, date, line items, and total.",
        },
        {"type": "image", "uri": receipt.uri, "mime_type": receipt.mime_type},
    ],
    response_format={
        "type": "text",
        "mime_type": "application/json",
        "schema": Receipt.model_json_schema(),
    },
)

data = Receipt.model_validate_json(interaction.output_text)
print(data.merchant, data.total)

अगर मॉडल कोई ऐसा जवाब दे जो स्कीमा में फ़िट न हो, तो model_validate_json वहीं एरर उठा देता है, ताकि खराब डेटा आपके डेटाबेस तक न पहुँचे।

बॉक्स के साथ ऑब्जेक्ट डिटेक्शन

संतरे, टमाटर और शिमला मिर्च के क्रेट वाली किराना गलियारा

Gemini बाउंडिंग बॉक्स को [ymin, xmin, ymax, xmax] के रूप में लौटा सकता है, जो 0 से 1000 के स्केल पर नॉर्मलाइज़्ड होते हैं। उन्हें स्कीमा के साथ माँगें, फिर पिक्सल में बदलकर बनाएँ:

from PIL import Image, ImageDraw
from pydantic import BaseModel, Field

class Box(BaseModel):
    box_2d: list[int] = Field(
        description="[ymin, xmin, ymax, xmax] normalized to 0-1000."
    )
    label: str

class Boxes(BaseModel):
    boxes: list[Box]

aisle = client.files.upload(file="grocery-aisle.jpg")

interaction = client.interactions.create(
    model="gemini-3.8-flash",
    input=[
        {"type": "text", "text": "Detect all of the prominent items in the image."},
        {"type": "image", "uri": aisle.uri, "mime_type": aisle.mime_type},
    ],
    response_format={
        "type": "text",
        "mime_type": "application/json",
        "schema": Boxes.model_json_schema(),
    },
)

result = Boxes.model_validate_json(interaction.output_text)

image = Image.open("grocery-aisle.jpg")
width, height = image.size
draw = ImageDraw.Draw(image)

for item in result.boxes:
    ymin, xmin, ymax, xmax = item.box_2d
    left, top = xmin / 1000 * width, ymin / 1000 * height
    right, bottom = xmax / 1000 * width, ymax / 1000 * height
    draw.rectangle((left, top, right, bottom), outline="red", width=4)
    draw.text((left + 6, top + 6), item.label, fill="red")

image.save("grocery-aisle-boxes.jpg")

सेगमेंटेशन भी इसी पैटर्न पर चलता है। स्कीमा में एक mask फ़ील्ड जुड़ता है जिसमें पॉलीगन पॉइंट होते हैं, जो भी 0 से 1000 पर नॉर्मलाइज़्ड होते हैं। सेगमेंटेशन के लिए Google minimal थिंकिंग लेवल सेट करने की सलाह देता है, क्योंकि एक्सटेंडेड रीज़निंग पॉलीगन सुधारे बिना लेटेंसी बढ़ाती है।

सीमाएँ, टोकन और लागत

लाइट टेबल पर लूपर के साथ छोटे फ़्रेम की कॉन्टैक्ट शीट

इमेज का बिल टोकन में बनता है, और गिनती साइज़ पर निर्भर करती है। नियम जानने से बैच चलने से पहले ही बिल का अंदाज़ा लग जाता है।

इमेज टोकन में कैसे गिनी जाती हैं

इमेज की स्थितिटोकन लागत
दोनों आयाम 384 px या उससे छोटे258 टोकन
बड़ी इमेज768 x 768 px के टाइल्स में बाँटी जाती है, हर टाइल पर 258 टोकन
उदाहरण: चार टाइल्स में बँटने वाली इमेज4 x 258 = 1,032 टोकन

डॉक्स एक media_resolution सेटिंग भी बताते हैं, जो हर इनपुट इमेज को दिए जाने वाले अधिकतम टोकन की सीमा तय करती है। बड़े पैमाने पर कैप्शनिंग में, जहाँ बारीक विवरण मायने नहीं रखता, इसे कम रखें। जब छोटे प्रिंट या दूर की चीज़ें मायने रखें, तब इसे बढ़ाएँ। आपके SDK वर्ज़न में यह विकल्प किस नाम से लिखा जाता है, यह मौजूदा रेफ़रेंस में जाँचें।

कीमतें मॉडल के हिसाब से अलग होती हैं, इसलिए संख्याओं के लिए Google का प्राइसिंग पेज पढ़ें। जिस पर आपका नियंत्रण है, वह टोकन गिनती है, और फ़ाइल की छोटी कॉपी भेजना उसे घटाने का सबसे सस्ता तरीका है।

फ़ॉर्मेट और साइज़ की सीमाएँ

सीमामान
समर्थित फ़ॉर्मेटPNG, JPEG, WEBP, HEIC, HEIF
प्रति रिक्वेस्ट इमेज3,600 फ़ाइलों तक
इनलाइन रिक्वेस्ट का साइज़कुल 20 MB (टेक्स्ट, इंस्ट्रक्शन और बाइट्स)
बाउंडिंग बॉक्स स्केल0 से 1000, क्रम [ymin, xmin, ymax, xmax]

💡 अगर कोई जॉब लंबे प्रॉम्प्ट के साथ कई इमेज भेजता है, तो 20 MB की दीवार से टकराने से पहले इनलाइन कुल योग गिन लें। प्रोजेक्ट के बीच में Files API पर जाना आसान है, लेकिन शुरू में ही ऐसा करने से 2 बजे रात की अस्थिर विफलता से बचा जा सकता है।

तीन गलतियाँ जो कॉल बर्बाद करती हैं

ज़्यादातर विफल रिक्वेस्ट इसी छोटी सूची से आती हैं।

गलत MIME टाइप

mime_type असली फ़ाइल से मेल खाना चाहिए। PNG को image/jpeg लिखना या असमर्थित फ़ॉर्मेट भेजना एरर या खराब नतीजे देता है। स्ट्रिंग हाथ से टाइप करने के बजाय Python को तय करने दें:

import mimetypes

def mime_for(path: str) -> str:
    mime, _ = mimetypes.guess_type(path)
    if mime is None:
        raise ValueError(f"Unknown image type: {path}")
    return mime

कुछ सिस्टम HEIC टाइप नहीं जानते, इसलिए अगर आप iPhone की ओरिजिनल फ़ाइलें स्वीकार करते हैं, तो एक छोटी मैन्युअल मैपिंग जोड़ें।

गलत जगह पर बॉक्स

अगर बनाए गए आयत अजीब जगहों पर आएँ, तो दो बातें जाँचें। पहली, क्रम [ymin, xmin, ymax, xmax] है, जिसमें पहले वर्टिकल मान आता है। कई लोग इसे x फिर y पढ़ते हैं। दूसरी, संख्याएँ 0 से 1000 के स्केल पर हैं, पिक्सल में नहीं। 1000 से भाग दें, फिर असली चौड़ाई या ऊँचाई से गुणा करें।

JSON की जगह फ़्री टेक्स्ट

प्रॉम्प्ट में "JSON लौटाएँ" लिखना तब तक चलता है जब तक मॉडल जवाब को कोड फ़ेंस में नहीं लपेटता या कोई दोस्ताना वाक्य नहीं जोड़ता। response_format के ज़रिए स्कीमा पास करें और model_validate_json से पार्स करें। तब अनुबंध कोड में रहता है, जहाँ खराब जवाब ज़ोर से फ़ेल होता है और अच्छा जवाब टाइप्ड होकर आता है।

कोड के बिना Gemini 3.5 Flash आज़माएँ

Python लिखने से पहले ब्राउज़र में प्रॉम्प्ट आज़माएँ। Gemini 3.5 Flash Picasso IA पर चलता है और इमेज सीधे लेता है, इसलिए आप कुछ ही सेकंड में इंस्ट्रक्शन ठीक कर सकते हैं और बाद में उसे अपनी स्क्रिप्ट में चिपका सकते हैं।

  1. Picasso IA पर Gemini 3.5 Flash पेज खोलें।
  2. अपनी फ़ोटो Images फ़ील्ड में अटैच करें। मॉडल एक रन में अधिकतम 10 इमेज लेता है, हर एक 7 MB तक।
  3. Prompt फ़ील्ड में इंस्ट्रक्शन टाइप करें, ठीक वैसे ही शब्दों में जैसे आप उसे Python से भेजने की योजना बना रहे हैं।
  4. चाहें तो System Instruction भरकर भूमिका तय करें, जैसे "आप 125 अक्षरों से कम के alt text लिखते हैं।"
  5. Thinking Level none, low या high चुनें। कैप्शन के लिए none रखें और घनी रीज़निंग के लिए बढ़ाएँ।
  6. एक्सट्रैक्शन और OCR के लिए Temperature कम रखें, क्रिएटिव कैप्शन के लिए ज़्यादा।
  7. रन करें, जवाब की तुलना अपनी उम्मीद से करें, और कोड में कॉपी करने से पहले शब्द ठीक करें।
फ़ील्डयह क्या करता हैशुरुआती मान
Promptवह इंस्ट्रक्शन जो इमेज के साथ भेजा जाता हैआपके प्रोडक्शन में इस्तेमाल होने वाले ठीक शब्द
Imagesअधिकतम 10 फ़ाइलें, हर एक 7 MBटेस्टिंग के समय एक इमेज
System Instructionमॉडल की भूमिका तय करता हैएक छोटा वाक्य
Thinking Levelnone, low या highnone
Temperature0 से 2 तक रैंडमनेसOCR के लिए 0.2, कैप्शन के लिए 1
Max Output Tokensजवाब की लंबाई की सीमा तय करता हैडिफ़ॉल्ट ठीक है

Picasso IA पर सीमाएँ ऊपर दिए रॉ API की सीमाओं से अलग हैं, इसलिए इस पेज को प्रॉम्प्ट लैब और API को प्रोडक्शन का रास्ता मानें। किसी मुश्किल इमेज पर दूसरी राय के लिए वही प्रॉम्प्ट Gemini 3.1 Pro, Qwen3.7-Plus, जो टेक्स्ट की तरह इमेज भी समझता है, या Granite Vision 4.1 4B, जो चार्ट और टेबल के लिए बना है, पर चलाएँ।

अपनी टेस्ट इमेज खुद बनाएँ

शुरू करने के लिए असली फ़ोटो के फ़ोल्डर की ज़रूरत नहीं है। PicassoIA Image या Seedream 4.5 से एक बिखरी मेज़, किराना शेल्फ़, बारिश वाली सड़क या मुड़ी हुई रसीद बनाएँ, फिर हर नतीजा Gemini 3.5 Flash को दें और देखें कि वह उसमें से क्या पढ़ता है।

इस हफ़्ते तीन प्रयोग करें। पाँच बनाई गई फ़ोटो पर alt text माँगें। किसी भीड़भाड़ वाले दृश्य में एक ऑब्जेक्ट के चारों ओर बाउंडिंग बॉक्स माँगें। किसी रसीद की इमेज से JSON में कुल योग माँगें। हर एक में कुछ ही मिनट लगते हैं, और साथ मिलकर दिखाते हैं कि मॉडल कहाँ तेज़ है और आपके प्रॉम्प्ट को कहाँ और कसने की ज़रूरत है।

Picasso IA खोलें, अपनी पहली टेस्ट इमेज बनाएँ और अपना प्रॉम्प्ट चलाएँ। हर उपलब्ध मॉडल picassoia.com/en/all-models पर देखें और इमेज जनरेटर को विज़न मॉडल के साथ जोड़कर अपना इमेज-टू-टेक्स्ट वर्कफ़्लो बनाएँ।

यह लेख शेयर करें

अपनी भाषा चुनें

संबंधित लेख